xrpld
Loading...
Searching...
No Matches
Units.cpp
1#include <xrpl/protocol/Units.h>
2
3#include <xrpl/beast/utility/Zero.h>
4#include <xrpl/json/json_value.h>
5#include <xrpl/protocol/SystemParameters.h>
6#include <xrpl/protocol/XRPAmount.h>
7
8#include <gtest/gtest.h>
9
10#include <cstdint>
11#include <limits>
12#include <type_traits>
13
14namespace xrpl::test {
15
16TEST(UnitsTest, types)
17{
18 using FeeLevel32 = FeeLevel<std::uint32_t>;
19
20 {
21 XRPAmount const x{100};
22 EXPECT_EQ(x.drops(), 100);
23 EXPECT_TRUE((std::is_same_v<decltype(x)::unit_type, unit::dropTag>));
24 auto y = 4u * x;
25 EXPECT_EQ(y.value(), 400);
26 EXPECT_TRUE((std::is_same_v<decltype(y)::unit_type, unit::dropTag>));
27
28 auto z = 4 * y;
29 EXPECT_EQ(z.value(), 1600);
30 EXPECT_TRUE((std::is_same_v<decltype(z)::unit_type, unit::dropTag>));
31
32 FeeLevel32 const f{10};
33 FeeLevel32 const baseFee{100};
34
35 auto drops = mulDiv(baseFee, x, f);
36
37 EXPECT_TRUE(drops);
38 EXPECT_EQ(drops.value(), 1000); // NOLINT(bugprone-unchecked-optional-access)
39 EXPECT_TRUE(
40 (std::is_same_v<std::remove_reference_t<decltype(*drops)>::unit_type, unit::dropTag>));
41
42 EXPECT_TRUE((std::is_same_v<std::remove_reference_t<decltype(*drops)>, XRPAmount>));
43 }
44 {
45 XRPAmount const x{100};
46 EXPECT_EQ(x.value(), 100);
47 EXPECT_TRUE((std::is_same_v<decltype(x)::unit_type, unit::dropTag>));
48 auto y = 4u * x;
49 EXPECT_EQ(y.value(), 400);
50 EXPECT_TRUE((std::is_same_v<decltype(y)::unit_type, unit::dropTag>));
51
52 FeeLevel64 const f{10};
53 FeeLevel64 const baseFee{100};
54
55 auto drops = mulDiv(baseFee, x, f);
56
57 EXPECT_TRUE(drops);
58 EXPECT_EQ(drops.value(), 1000); // NOLINT(bugprone-unchecked-optional-access)
59 EXPECT_TRUE(
60 (std::is_same_v<std::remove_reference_t<decltype(*drops)>::unit_type, unit::dropTag>));
61 EXPECT_TRUE((std::is_same_v<std::remove_reference_t<decltype(*drops)>, XRPAmount>));
62 }
63 {
64 FeeLevel64 const x{1024};
65 EXPECT_EQ(x.value(), 1024);
66 EXPECT_TRUE((std::is_same_v<decltype(x)::unit_type, unit::feelevelTag>));
67 std::uint64_t const m = 4;
68 auto y = m * x;
69 EXPECT_EQ(y.value(), 4096);
70 EXPECT_TRUE((std::is_same_v<decltype(y)::unit_type, unit::feelevelTag>));
71
72 XRPAmount const basefee{10};
73 FeeLevel64 const referencefee{256};
74
75 auto drops = mulDiv(x, basefee, referencefee);
76
77 EXPECT_TRUE(drops);
78 EXPECT_EQ(drops.value(), 40); // NOLINT(bugprone-unchecked-optional-access)
79 EXPECT_TRUE(
80 (std::is_same_v<std::remove_reference_t<decltype(*drops)>::unit_type, unit::dropTag>));
81 EXPECT_TRUE((std::is_same_v<std::remove_reference_t<decltype(*drops)>, XRPAmount>));
82 }
83}
84
85TEST(UnitsTest, json)
86{
87 // Json value functionality
88 using FeeLevel32 = FeeLevel<std::uint32_t>;
89
90 {
91 FeeLevel32 const x{std::numeric_limits<std::uint32_t>::max()};
92 auto y = x.jsonClipped();
93 EXPECT_EQ(y.type(), json::ValueType::UInt);
94 EXPECT_EQ(y, json::Value{x.fee()});
95 }
96
97 {
98 FeeLevel32 const x{std::numeric_limits<std::uint32_t>::min()};
99 auto y = x.jsonClipped();
100 EXPECT_EQ(y.type(), json::ValueType::UInt);
101 EXPECT_EQ(y, json::Value{x.fee()});
102 }
103
104 {
106 auto y = x.jsonClipped();
107 EXPECT_EQ(y.type(), json::ValueType::UInt);
109 }
110
111 {
113 auto y = x.jsonClipped();
114 EXPECT_EQ(y.type(), json::ValueType::UInt);
115 EXPECT_EQ(y, json::Value{0});
116 }
117
118 {
120 auto y = x.jsonClipped();
121 EXPECT_EQ(y.type(), json::ValueType::Real);
123 }
124
125 {
127 auto y = x.jsonClipped();
128 EXPECT_EQ(y.type(), json::ValueType::Real);
130 }
131
132 {
134 auto y = x.jsonClipped();
135 EXPECT_EQ(y.type(), json::ValueType::Int);
137 }
138
139 {
141 auto y = x.jsonClipped();
142 EXPECT_EQ(y.type(), json::ValueType::Int);
144 }
145}
146
147TEST(UnitsTest, functions)
148{
149 // Explicitly test every defined function for the ValueUnit class
150 // since some of them are templated, but not used anywhere else.
151 using FeeLevel32 = FeeLevel<std::uint32_t>;
152
153 {
154 auto make = [&](auto x) -> FeeLevel64 { return x; };
155 auto explicitmake = [&](auto x) -> FeeLevel64 { return FeeLevel64{x}; };
156
157 [[maybe_unused]]
158 FeeLevel64 const defaulted{};
159 FeeLevel64 test{0};
160 EXPECT_EQ(test.fee(), 0);
161
162 test = explicitmake(beast::kZero);
163 EXPECT_EQ(test.fee(), 0);
164
166 EXPECT_EQ(test.fee(), 0);
167
168 test = explicitmake(100u);
169 EXPECT_EQ(test.fee(), 100);
170
171 FeeLevel64 const targetSame{200u};
172 FeeLevel32 const targetOther{300u};
173 test = make(targetSame);
174 EXPECT_EQ(test.fee(), 200);
175 EXPECT_EQ(test, targetSame);
176 EXPECT_TRUE(test < FeeLevel64{1000});
177 EXPECT_TRUE(test > FeeLevel64{100});
178 test = make(targetOther);
179 EXPECT_EQ(test.fee(), 300);
180 EXPECT_EQ(test, targetOther);
181
182 test = std::uint64_t(200);
183 EXPECT_EQ(test.fee(), 200);
184 test = std::uint32_t(300);
185 EXPECT_EQ(test.fee(), 300);
186
187 test = targetSame;
188 EXPECT_EQ(test.fee(), 200);
189 test = targetOther.fee();
190 EXPECT_EQ(test.fee(), 300);
191 EXPECT_EQ(test, targetOther);
192
193 test = targetSame * 2;
194 EXPECT_EQ(test.fee(), 400);
195 test = 3 * targetSame;
196 EXPECT_EQ(test.fee(), 600);
197 test = targetSame / 10;
198 EXPECT_EQ(test.fee(), 20);
199
200 test += targetSame;
201 EXPECT_EQ(test.fee(), 220);
202
203 test -= targetSame;
204 EXPECT_EQ(test.fee(), 20);
205
206 test++;
207 EXPECT_EQ(test.fee(), 21);
208 ++test;
209 EXPECT_EQ(test.fee(), 22);
210 test--;
211 EXPECT_EQ(test.fee(), 21);
212 --test;
213 EXPECT_EQ(test.fee(), 20);
214
215 test *= 5;
216 EXPECT_EQ(test.fee(), 100);
217 test /= 2;
218 EXPECT_EQ(test.fee(), 50);
219 test %= 13;
220 EXPECT_EQ(test.fee(), 11);
221
222 /*
223 // illegal with unsigned
224 test = -test;
225 EXPECT_EQ(test.fee(), -11);
226 EXPECT_EQ(test.signum(), -1);
227 EXPECT_EQ(to_string(test), "-11");
228 */
229
230 EXPECT_TRUE(test);
231 test = 0;
232 EXPECT_FALSE(test);
233 EXPECT_EQ(test.signum(), 0);
234 test = targetSame;
235 EXPECT_EQ(test.signum(), 1);
236 EXPECT_EQ(to_string(test), "200");
237 }
238 {
239 auto make = [&](auto x) -> FeeLevelDouble { return x; };
240 auto explicitmake = [&](auto x) -> FeeLevelDouble { return FeeLevelDouble{x}; };
241
242 [[maybe_unused]]
243 FeeLevelDouble const defaulted{};
245 EXPECT_EQ(test.fee(), 0);
246
247 test = explicitmake(beast::kZero);
248 EXPECT_EQ(test.fee(), 0);
249
251 EXPECT_EQ(test.fee(), 0);
252
253 test = explicitmake(100.0);
254 EXPECT_EQ(test.fee(), 100);
255
256 FeeLevelDouble const targetSame{200.0};
257 FeeLevel64 const targetOther{300};
258 test = make(targetSame);
259 EXPECT_EQ(test.fee(), 200);
260 EXPECT_EQ(test, targetSame);
261 EXPECT_TRUE(test < FeeLevelDouble{1000.0});
262 EXPECT_TRUE(test > FeeLevelDouble{100.0});
263 test = targetOther.fee();
264 EXPECT_EQ(test.fee(), 300);
265 EXPECT_EQ(test, targetOther);
266
267 test = 200.0;
268 EXPECT_EQ(test.fee(), 200);
269 test = std::uint64_t(300);
270 EXPECT_EQ(test.fee(), 300);
271
272 test = targetSame;
273 EXPECT_EQ(test.fee(), 200);
274
275 test = targetSame * 2;
276 EXPECT_EQ(test.fee(), 400);
277 test = 3 * targetSame;
278 EXPECT_EQ(test.fee(), 600);
279 test = targetSame / 10;
280 EXPECT_EQ(test.fee(), 20);
281
282 test += targetSame;
283 EXPECT_EQ(test.fee(), 220);
284
285 test -= targetSame;
286 EXPECT_EQ(test.fee(), 20);
287
288 test++;
289 EXPECT_EQ(test.fee(), 21);
290 ++test;
291 EXPECT_EQ(test.fee(), 22);
292 test--;
293 EXPECT_EQ(test.fee(), 21);
294 --test;
295 EXPECT_EQ(test.fee(), 20);
296
297 test *= 5;
298 EXPECT_EQ(test.fee(), 100);
299 test /= 2;
300 EXPECT_EQ(test.fee(), 50);
301 /* illegal with floating
302 test %= 13;
303 EXPECT_EQ(test.fee(), 11);
304 */
305
306 // legal with signed
307 test = -test;
308 EXPECT_EQ(test.fee(), -50);
309 EXPECT_EQ(test.signum(), -1);
310 EXPECT_EQ(to_string(test), "-50.000000");
311
312 EXPECT_TRUE(test);
313 test = 0;
314 EXPECT_FALSE(test);
315 EXPECT_EQ(test.signum(), 0);
316 test = targetSame;
317 EXPECT_EQ(test.signum(), 1);
318 EXPECT_EQ(to_string(test), "200.000000");
319 }
320}
321
322TEST(UnitsTest, initial_xrp)
323{
324 EXPECT_EQ(kInitialXrp.drops(), 100'000'000'000'000'000);
325 EXPECT_EQ(kInitialXrp, XRPAmount{100'000'000'000'000'000});
326}
327
328} // namespace xrpl::test
Represents a JSON value.
Definition json_value.h:117
json::Value jsonClipped() const
Definition XRPAmount.h:210
constexpr value_type value() const
Returns the underlying value.
Definition XRPAmount.h:232
constexpr value_type drops() const
Returns the number of drops.
Definition XRPAmount.h:170
constexpr value_type value() const
Returns the underlying value.
Definition Units.h:338
json::Value jsonClipped() const
Definition Units.h:309
constexpr value_type fee() const
Returns the number of drops.
Definition Units.h:292
T is_same_v
T max(T... args)
T min(T... args)
constexpr Zero kZero
Definition Zero.h:30
JSON (JavaScript Object Notation).
Definition json_errors.h:5
@ UInt
unsigned integer value
Definition json_value.h:24
@ Int
signed integer value
Definition json_value.h:23
@ Real
double value
Definition json_value.h:25
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
TEST(UnitsTest, types)
Definition Units.cpp:16
constexpr XRPAmount
Convert XRP to drops (integral types).
Definition TxTest.h:54
std::optional< std::uint64_t > mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
Return value*mul/div accurately.
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:651
FeeLevel< std::uint64_t > FeeLevel64
Definition Units.h:443
FeeLevel< double > FeeLevelDouble
Definition Units.h:444
unit::ValueUnit< unit::feelevelTag, T > FeeLevel
Definition Units.h:442
constexpr XRPAmount kInitialXrp
Configure the native currency.