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 const mantissa : mantissas)
49 testCombo(Number{mantissa});
50
51 std::initializer_list<std::int32_t> const exponents = {
53 for (std::int32_t const 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 const totalValue{iouValue * factor};
61 STAmount const totalAmount{totalValue, strikePrice.issue()};
62 BEAST_EXPECT(totalAmount == Number{10'000});
63 }
64
65 {
66 BEAST_EXPECT(numberFromJson(sfNumber, Json::Value(42)) == STNumber(sfNumber, 42));
67 BEAST_EXPECT(numberFromJson(sfNumber, Json::Value(-42)) == STNumber(sfNumber, -42));
68
69 BEAST_EXPECT(numberFromJson(sfNumber, Json::UInt(42)) == STNumber(sfNumber, 42));
70
71 BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
72
73 BEAST_EXPECT(numberFromJson(sfNumber, "123") == STNumber(sfNumber, 123));
74 BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
75
76 BEAST_EXPECT(numberFromJson(sfNumber, "3.14") == STNumber(sfNumber, Number(314, -2)));
77 BEAST_EXPECT(numberFromJson(sfNumber, "-3.14") == STNumber(sfNumber, -Number(314, -2)));
78 BEAST_EXPECT(numberFromJson(sfNumber, "3.14e2") == STNumber(sfNumber, 314));
79 BEAST_EXPECT(numberFromJson(sfNumber, "-3.14e2") == STNumber(sfNumber, -314));
80
81 BEAST_EXPECT(numberFromJson(sfNumber, "1000e-2") == STNumber(sfNumber, 10));
82 BEAST_EXPECT(numberFromJson(sfNumber, "-1000e-2") == STNumber(sfNumber, -10));
83
84 BEAST_EXPECT(numberFromJson(sfNumber, "0") == STNumber(sfNumber, 0));
85 BEAST_EXPECT(numberFromJson(sfNumber, "0.0") == STNumber(sfNumber, 0));
86 BEAST_EXPECT(numberFromJson(sfNumber, "0.000") == STNumber(sfNumber, 0));
87 BEAST_EXPECT(numberFromJson(sfNumber, "-0") == STNumber(sfNumber, 0));
88 BEAST_EXPECT(numberFromJson(sfNumber, "-0.0") == STNumber(sfNumber, 0));
89 BEAST_EXPECT(numberFromJson(sfNumber, "-0.000") == STNumber(sfNumber, 0));
90 BEAST_EXPECT(numberFromJson(sfNumber, "0e6") == STNumber(sfNumber, 0));
91 BEAST_EXPECT(numberFromJson(sfNumber, "0.0e6") == STNumber(sfNumber, 0));
92 BEAST_EXPECT(numberFromJson(sfNumber, "0.000e6") == STNumber(sfNumber, 0));
93 BEAST_EXPECT(numberFromJson(sfNumber, "-0e6") == STNumber(sfNumber, 0));
94 BEAST_EXPECT(numberFromJson(sfNumber, "-0.0e6") == STNumber(sfNumber, 0));
95 BEAST_EXPECT(numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0));
96
97 {
99 // maxint64 9,223,372,036,854,775,807
101 // minint64 -9,223,372,036,854,775,808
104 {
105 BEAST_EXPECT(
106 numberFromJson(sfNumber, maxInt) ==
107 STNumber(sfNumber, Number{9'223'372'036'854'775, 3}));
108 BEAST_EXPECT(
109 numberFromJson(sfNumber, minInt) ==
110 STNumber(sfNumber, Number{-9'223'372'036'854'775, 3}));
111 }
112 else
113 {
114 BEAST_EXPECT(
115 numberFromJson(sfNumber, maxInt) ==
116 STNumber(sfNumber, Number{9'223'372'036'854'775'807, 0}));
117 BEAST_EXPECT(
118 numberFromJson(sfNumber, minInt) ==
119 STNumber(
120 sfNumber,
121 Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}}));
122 }
123 }
124
125 constexpr auto imin = std::numeric_limits<int>::min();
126 BEAST_EXPECT(numberFromJson(sfNumber, imin) == STNumber(sfNumber, Number(imin, 0)));
127 BEAST_EXPECT(
128 numberFromJson(sfNumber, std::to_string(imin)) ==
129 STNumber(sfNumber, Number(imin, 0)));
130
131 constexpr auto imax = std::numeric_limits<int>::max();
132 BEAST_EXPECT(numberFromJson(sfNumber, imax) == STNumber(sfNumber, Number(imax, 0)));
133 BEAST_EXPECT(
134 numberFromJson(sfNumber, std::to_string(imax)) ==
135 STNumber(sfNumber, Number(imax, 0)));
136
137 constexpr auto umax = std::numeric_limits<unsigned int>::max();
138 BEAST_EXPECT(numberFromJson(sfNumber, umax) == STNumber(sfNumber, Number(umax, 0)));
139 BEAST_EXPECT(
140 numberFromJson(sfNumber, std::to_string(umax)) ==
141 STNumber(sfNumber, Number(umax, 0)));
142
143 // Obvious non-numbers tested here
144 try
145 {
146 auto _ = numberFromJson(sfNumber, "");
147 BEAST_EXPECT(false);
148 }
149 catch (std::runtime_error const& e)
150 {
151 std::string const expected = "'' is not a number";
152 BEAST_EXPECT(e.what() == expected);
153 }
154
155 try
156 {
157 auto _ = numberFromJson(sfNumber, "e");
158 BEAST_EXPECT(false);
159 }
160 catch (std::runtime_error const& e)
161 {
162 std::string const expected = "'e' is not a number";
163 BEAST_EXPECT(e.what() == expected);
164 }
165
166 try
167 {
168 auto _ = numberFromJson(sfNumber, "1e");
169 BEAST_EXPECT(false);
170 }
171 catch (std::runtime_error const& e)
172 {
173 std::string const expected = "'1e' is not a number";
174 BEAST_EXPECT(e.what() == expected);
175 }
176
177 try
178 {
179 auto _ = numberFromJson(sfNumber, "e2");
180 BEAST_EXPECT(false);
181 }
182 catch (std::runtime_error const& e)
183 {
184 std::string const expected = "'e2' is not a number";
185 BEAST_EXPECT(e.what() == expected);
186 }
187
188 try
189 {
190 auto _ = numberFromJson(sfNumber, Json::Value());
191 BEAST_EXPECT(false);
192 }
193 catch (std::runtime_error const& e)
194 {
195 std::string const expected = "not a number";
196 BEAST_EXPECT(e.what() == expected);
197 }
198
199 try
200 {
201 auto _ = numberFromJson(
202 sfNumber,
203 "1234567890123456789012345678901234567890123456789012345678"
204 "9012345678901234567890123456789012345678901234567890123456"
205 "78901234567890123456789012345678901234567890");
206 BEAST_EXPECT(false);
207 }
208 catch (std::bad_cast const& e)
209 {
210 BEAST_EXPECT(true);
211 }
212
213 // We do not handle leading zeros
214 try
215 {
216 auto _ = numberFromJson(sfNumber, "001");
217 BEAST_EXPECT(false);
218 }
219 catch (std::runtime_error const& e)
220 {
221 std::string const expected = "'001' is not a number";
222 BEAST_EXPECT(e.what() == expected);
223 }
224
225 try
226 {
227 auto _ = numberFromJson(sfNumber, "000.0");
228 BEAST_EXPECT(false);
229 }
230 catch (std::runtime_error const& e)
231 {
232 std::string const expected = "'000.0' is not a number";
233 BEAST_EXPECT(e.what() == expected);
234 }
235
236 // We do not handle dangling dot
237 try
238 {
239 auto _ = numberFromJson(sfNumber, ".1");
240 BEAST_EXPECT(false);
241 }
242 catch (std::runtime_error const& e)
243 {
244 std::string const expected = "'.1' is not a number";
245 BEAST_EXPECT(e.what() == expected);
246 }
247
248 try
249 {
250 auto _ = numberFromJson(sfNumber, "1.");
251 BEAST_EXPECT(false);
252 }
253 catch (std::runtime_error const& e)
254 {
255 std::string const expected = "'1.' is not a number";
256 BEAST_EXPECT(e.what() == expected);
257 }
258
259 try
260 {
261 auto _ = numberFromJson(sfNumber, "1.e3");
262 BEAST_EXPECT(false);
263 }
264 catch (std::runtime_error const& e)
265 {
266 std::string const expected = "'1.e3' is not a number";
267 BEAST_EXPECT(e.what() == expected);
268 }
269 }
270 }
271
272 void
273 run() override
274 {
276
277 for (auto const scale : {MantissaRange::small, MantissaRange::large})
278 {
279 NumberMantissaScaleGuard const sg(scale);
281 doRun();
282 }
283 }
284};
285
286BEAST_DEFINE_TESTSUITE(STNumber, protocol, xrpl);
287
288} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
A testsuite class.
Definition suite.h:51
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:150
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:25
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:814
Number is a floating point type that can represent a wide range of values.
Definition Number.h:207
static constexpr int minExponent
Definition Number.h:217
static constexpr int maxExponent
Definition Number.h:218
static MantissaRange::mantissa_scale getMantissaScale()
Returns which mantissa scale is currently in use for normalization.
Definition Number.cpp:45
Issue const & issue() const
Definition STAmount.h:470
A serializable number.
Definition STNumber.h:35
Slice slice() const noexcept
Definition Serializer.h:44
std::size_t size() const noexcept
Definition Serializer.h:50
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:5
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:602
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:523
STNumber numberFromJson(SField const &field, Json::Value const &value)
Definition STNumber.cpp:214
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
Definition Issue.h:105
void testCombo(Number number)
void run() override
Runs the suite.
T to_string(T... args)
T what(T... args)