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