xrpld
Loading...
Searching...
No Matches
STNumber_test.cpp
1#include <xrpl/basics/Number.h>
2#include <xrpl/beast/unit_test/suite.h>
3#include <xrpl/json/json_forwards.h>
4#include <xrpl/protocol/IOUAmount.h>
5#include <xrpl/protocol/Issue.h>
6#include <xrpl/protocol/SField.h>
7#include <xrpl/protocol/STAmount.h>
8#include <xrpl/protocol/STNumber.h>
9#include <xrpl/protocol/Serializer.h>
10
11#include <cstdint>
12#include <initializer_list>
13#include <limits>
14#include <stdexcept>
15#include <string>
16#include <type_traits>
17#include <typeinfo>
18
19namespace xrpl {
20
22{
23 void
25 {
26 STNumber const before{sfNumber, number};
27 BEAST_EXPECT(number == before);
28 Serializer s;
29 before.add(s);
30 BEAST_EXPECT(s.size() == 12);
31 SerialIter sit(s.slice());
32 STNumber const after{sit, sfNumber};
33 BEAST_EXPECT(after.isEquivalent(before));
34 BEAST_EXPECT(number == after);
35 }
36
37 void
39 {
40 {
41 STNumber const stnum{sfNumber};
42 BEAST_EXPECT(stnum.getSType() == STI_NUMBER);
43 BEAST_EXPECT(stnum.getText() == "0");
44 BEAST_EXPECT(stnum.isDefault() == true);
45 BEAST_EXPECT(stnum.value() == Number{0});
46 }
47
48 std::initializer_list<std::int64_t> const mantissas = {
50 -1,
51 0,
52 1,
54 for (std::int64_t const mantissa : mantissas)
55 testCombo(Number{mantissa});
56
57 std::initializer_list<std::int32_t> const exponents = {
59 for (std::int32_t const exponent : exponents)
60 testCombo(Number{123, exponent});
61
62 {
63 STAmount const strikePrice{noIssue(), 100};
64 STNumber const factor{sfNumber, 100};
65 auto const iouValue = strikePrice.iou();
66 IOUAmount const totalValue{iouValue * factor};
67 STAmount const totalAmount{totalValue, strikePrice.get<Issue>()};
68 BEAST_EXPECT(totalAmount == Number{10'000});
69 }
70
71 {
72 BEAST_EXPECT(numberFromJson(sfNumber, json::Value(42)) == STNumber(sfNumber, 42));
73 BEAST_EXPECT(numberFromJson(sfNumber, json::Value(-42)) == STNumber(sfNumber, -42));
74
75 BEAST_EXPECT(numberFromJson(sfNumber, json::UInt(42)) == STNumber(sfNumber, 42));
76
77 BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
78
79 BEAST_EXPECT(numberFromJson(sfNumber, "123") == STNumber(sfNumber, 123));
80 BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
81
82 BEAST_EXPECT(numberFromJson(sfNumber, "3.14") == STNumber(sfNumber, Number(314, -2)));
83 BEAST_EXPECT(numberFromJson(sfNumber, "-3.14") == STNumber(sfNumber, -Number(314, -2)));
84 BEAST_EXPECT(numberFromJson(sfNumber, "3.14e2") == STNumber(sfNumber, 314));
85 BEAST_EXPECT(numberFromJson(sfNumber, "-3.14e2") == STNumber(sfNumber, -314));
86
87 BEAST_EXPECT(numberFromJson(sfNumber, "1000e-2") == STNumber(sfNumber, 10));
88 BEAST_EXPECT(numberFromJson(sfNumber, "-1000e-2") == STNumber(sfNumber, -10));
89
90 BEAST_EXPECT(numberFromJson(sfNumber, "0") == STNumber(sfNumber, 0));
91 BEAST_EXPECT(numberFromJson(sfNumber, "0.0") == STNumber(sfNumber, 0));
92 BEAST_EXPECT(numberFromJson(sfNumber, "0.000") == STNumber(sfNumber, 0));
93 BEAST_EXPECT(numberFromJson(sfNumber, "-0") == STNumber(sfNumber, 0));
94 BEAST_EXPECT(numberFromJson(sfNumber, "-0.0") == STNumber(sfNumber, 0));
95 BEAST_EXPECT(numberFromJson(sfNumber, "-0.000") == STNumber(sfNumber, 0));
96 BEAST_EXPECT(numberFromJson(sfNumber, "0e6") == STNumber(sfNumber, 0));
97 BEAST_EXPECT(numberFromJson(sfNumber, "0.0e6") == STNumber(sfNumber, 0));
98 BEAST_EXPECT(numberFromJson(sfNumber, "0.000e6") == STNumber(sfNumber, 0));
99 BEAST_EXPECT(numberFromJson(sfNumber, "-0e6") == STNumber(sfNumber, 0));
100 BEAST_EXPECT(numberFromJson(sfNumber, "-0.0e6") == STNumber(sfNumber, 0));
101 BEAST_EXPECT(numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0));
102
103 {
105 // maxint64 9,223,372,036,854,775,807
107 // minint64 -9,223,372,036,854,775,808
110 {
111 BEAST_EXPECT(
112 numberFromJson(sfNumber, maxInt) ==
113 STNumber(sfNumber, Number{9'223'372'036'854'775, 3}));
114 BEAST_EXPECT(
115 numberFromJson(sfNumber, minInt) ==
116 STNumber(sfNumber, Number{-9'223'372'036'854'775, 3}));
117 }
118 else
119 {
120 BEAST_EXPECT(
121 numberFromJson(sfNumber, maxInt) ==
122 STNumber(sfNumber, Number{9'223'372'036'854'775'807, 0}));
123 BEAST_EXPECT(
124 numberFromJson(sfNumber, minInt) ==
125 STNumber(
126 sfNumber,
127 Number{true, 9'223'372'036'854'775'808ULL, 0, Number::Normalized{}}));
128 }
129 }
130
131 constexpr auto kIMin = std::numeric_limits<int>::min();
132 BEAST_EXPECT(numberFromJson(sfNumber, kIMin) == STNumber(sfNumber, Number(kIMin, 0)));
133 BEAST_EXPECT(
134 numberFromJson(sfNumber, std::to_string(kIMin)) ==
135 STNumber(sfNumber, Number(kIMin, 0)));
136
137 constexpr auto kIMax = std::numeric_limits<int>::max();
138 BEAST_EXPECT(numberFromJson(sfNumber, kIMax) == STNumber(sfNumber, Number(kIMax, 0)));
139 BEAST_EXPECT(
140 numberFromJson(sfNumber, std::to_string(kIMax)) ==
141 STNumber(sfNumber, Number(kIMax, 0)));
142
143 constexpr auto kUMax = std::numeric_limits<unsigned int>::max();
144 BEAST_EXPECT(numberFromJson(sfNumber, kUMax) == STNumber(sfNumber, Number(kUMax, 0)));
145 BEAST_EXPECT(
146 numberFromJson(sfNumber, std::to_string(kUMax)) ==
147 STNumber(sfNumber, Number(kUMax, 0)));
148
149 // Obvious non-numbers tested here
150 try
151 {
152 auto _ = numberFromJson(sfNumber, "");
153 BEAST_EXPECT(false);
154 }
155 catch (std::runtime_error const& e)
156 {
157 std::string const expected = "'' is not a number";
158 BEAST_EXPECT(e.what() == expected);
159 }
160
161 try
162 {
163 auto _ = numberFromJson(sfNumber, "e");
164 BEAST_EXPECT(false);
165 }
166 catch (std::runtime_error const& e)
167 {
168 std::string const expected = "'e' is not a number";
169 BEAST_EXPECT(e.what() == expected);
170 }
171
172 try
173 {
174 auto _ = numberFromJson(sfNumber, "1e");
175 BEAST_EXPECT(false);
176 }
177 catch (std::runtime_error const& e)
178 {
179 std::string const expected = "'1e' is not a number";
180 BEAST_EXPECT(e.what() == expected);
181 }
182
183 try
184 {
185 auto _ = numberFromJson(sfNumber, "e2");
186 BEAST_EXPECT(false);
187 }
188 catch (std::runtime_error const& e)
189 {
190 std::string const expected = "'e2' is not a number";
191 BEAST_EXPECT(e.what() == expected);
192 }
193
194 try
195 {
196 auto _ = numberFromJson(sfNumber, json::Value());
197 BEAST_EXPECT(false);
198 }
199 catch (std::runtime_error const& e)
200 {
201 std::string const expected = "not a number";
202 BEAST_EXPECT(e.what() == expected);
203 }
204
205 try
206 {
207 auto _ = numberFromJson(
208 sfNumber,
209 "1234567890123456789012345678901234567890123456789012345678"
210 "9012345678901234567890123456789012345678901234567890123456"
211 "78901234567890123456789012345678901234567890");
212 BEAST_EXPECT(false);
213 }
214 catch (std::bad_cast const& e)
215 {
216 BEAST_EXPECT(true);
217 }
218
219 // We do not handle leading zeros
220 try
221 {
222 auto _ = numberFromJson(sfNumber, "001");
223 BEAST_EXPECT(false);
224 }
225 catch (std::runtime_error const& e)
226 {
227 std::string const expected = "'001' is not a number";
228 BEAST_EXPECT(e.what() == expected);
229 }
230
231 try
232 {
233 auto _ = numberFromJson(sfNumber, "000.0");
234 BEAST_EXPECT(false);
235 }
236 catch (std::runtime_error const& e)
237 {
238 std::string const expected = "'000.0' is not a number";
239 BEAST_EXPECT(e.what() == expected);
240 }
241
242 // We do not handle dangling dot
243 try
244 {
245 auto _ = numberFromJson(sfNumber, ".1");
246 BEAST_EXPECT(false);
247 }
248 catch (std::runtime_error const& e)
249 {
250 std::string const expected = "'.1' is not a number";
251 BEAST_EXPECT(e.what() == expected);
252 }
253
254 try
255 {
256 auto _ = numberFromJson(sfNumber, "1.");
257 BEAST_EXPECT(false);
258 }
259 catch (std::runtime_error const& e)
260 {
261 std::string const expected = "'1.' is not a number";
262 BEAST_EXPECT(e.what() == expected);
263 }
264
265 try
266 {
267 auto _ = numberFromJson(sfNumber, "1.e3");
268 BEAST_EXPECT(false);
269 }
270 catch (std::runtime_error const& e)
271 {
272 std::string const expected = "'1.e3' is not a number";
273 BEAST_EXPECT(e.what() == expected);
274 }
275 }
276 }
277
278 void
279 run() override
280 {
282
283 for (auto const scale : MantissaRange::getAllScales())
284 {
287 doRun();
288 }
289 }
290};
291
293
294} // namespace xrpl
A testsuite class.
Definition suite.h:50
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
Represents a JSON value.
Definition json_value.h:130
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:24
A currency issued by an account.
Definition Issue.h:13
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:920
Number is a floating point type that can represent a wide range of values.
Definition Number.h:306
static constexpr int kMinExponent
Definition Number.h:316
static MantissaRange::MantissaScale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
Definition Number.cpp:117
static constexpr int kMaxExponent
Definition Number.h:317
constexpr TIss const & get() const
IOUAmount iou() const
Definition STAmount.cpp:286
A serializable number.
Definition STNumber.h:35
void add(Serializer &s) const override
Definition STNumber.cpp:69
bool isDefault() const override
Definition STNumber.cpp:150
std::string getText() const override
Definition STNumber.cpp:50
SerializedTypeID getSType() const override
Definition STNumber.cpp:44
Number const & value() const
Definition STNumber.cpp:117
Slice slice() const noexcept
Definition Serializer.h:44
std::size_t size() const noexcept
Definition Serializer.h:50
T is_convertible_v
T max(T... args)
T min(T... args)
unsigned int UInt
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
int scale(Number const &number, Asset const &asset)
Get the scale of a Number for a given asset.
Definition STAmount.h:779
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:554
STNumber numberFromJson(SField const &field, json::Value const &value)
Definition STNumber.cpp:222
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
Definition Issue.h:105
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl)
static std::set< MantissaScale > const & getAllScales()
Definition Number.cpp:37
void testCombo(Number number)
void run() override
Runs the suite.
T to_string(T... args)
T what(T... args)