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 for (std::int64_t mantissa : mantissas)
45 testCombo(Number{mantissa});
46
48 for (std::int32_t exponent : exponents)
49 testCombo(Number{123, exponent});
50
51 {
52 STAmount const strikePrice{noIssue(), 100};
53 STNumber const factor{sfNumber, 100};
54 auto const iouValue = strikePrice.iou();
55 IOUAmount totalValue{iouValue * factor};
56 STAmount const totalAmount{totalValue, strikePrice.issue()};
57 BEAST_EXPECT(totalAmount == Number{10'000});
58 }
59
60 {
61 BEAST_EXPECT(numberFromJson(sfNumber, Json::Value(42)) == STNumber(sfNumber, 42));
62 BEAST_EXPECT(numberFromJson(sfNumber, Json::Value(-42)) == STNumber(sfNumber, -42));
63
64 BEAST_EXPECT(numberFromJson(sfNumber, Json::UInt(42)) == STNumber(sfNumber, 42));
65
66 BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
67
68 BEAST_EXPECT(numberFromJson(sfNumber, "123") == STNumber(sfNumber, 123));
69 BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
70
71 BEAST_EXPECT(numberFromJson(sfNumber, "3.14") == STNumber(sfNumber, Number(314, -2)));
72 BEAST_EXPECT(numberFromJson(sfNumber, "-3.14") == STNumber(sfNumber, -Number(314, -2)));
73 BEAST_EXPECT(numberFromJson(sfNumber, "3.14e2") == STNumber(sfNumber, 314));
74 BEAST_EXPECT(numberFromJson(sfNumber, "-3.14e2") == STNumber(sfNumber, -314));
75
76 BEAST_EXPECT(numberFromJson(sfNumber, "1000e-2") == STNumber(sfNumber, 10));
77 BEAST_EXPECT(numberFromJson(sfNumber, "-1000e-2") == STNumber(sfNumber, -10));
78
79 BEAST_EXPECT(numberFromJson(sfNumber, "0") == STNumber(sfNumber, 0));
80 BEAST_EXPECT(numberFromJson(sfNumber, "0.0") == STNumber(sfNumber, 0));
81 BEAST_EXPECT(numberFromJson(sfNumber, "0.000") == STNumber(sfNumber, 0));
82 BEAST_EXPECT(numberFromJson(sfNumber, "-0") == STNumber(sfNumber, 0));
83 BEAST_EXPECT(numberFromJson(sfNumber, "-0.0") == STNumber(sfNumber, 0));
84 BEAST_EXPECT(numberFromJson(sfNumber, "-0.000") == STNumber(sfNumber, 0));
85 BEAST_EXPECT(numberFromJson(sfNumber, "0e6") == STNumber(sfNumber, 0));
86 BEAST_EXPECT(numberFromJson(sfNumber, "0.0e6") == STNumber(sfNumber, 0));
87 BEAST_EXPECT(numberFromJson(sfNumber, "0.000e6") == STNumber(sfNumber, 0));
88 BEAST_EXPECT(numberFromJson(sfNumber, "-0e6") == STNumber(sfNumber, 0));
89 BEAST_EXPECT(numberFromJson(sfNumber, "-0.0e6") == STNumber(sfNumber, 0));
90 BEAST_EXPECT(numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0));
91
92 {
94 // maxint64 9,223,372,036,854,775,807
96 // minint64 -9,223,372,036,854,775,808
99 {
100 BEAST_EXPECT(
101 numberFromJson(sfNumber, maxInt) == STNumber(sfNumber, Number{9'223'372'036'854'775, 3}));
102 BEAST_EXPECT(
103 numberFromJson(sfNumber, minInt) == STNumber(sfNumber, Number{-9'223'372'036'854'775, 3}));
104 }
105 else
106 {
107 BEAST_EXPECT(
108 numberFromJson(sfNumber, maxInt) == STNumber(sfNumber, Number{9'223'372'036'854'775'807, 0}));
109 BEAST_EXPECT(
110 numberFromJson(sfNumber, minInt) ==
111 STNumber(sfNumber, Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}}));
112 }
113 }
114
115 constexpr auto imin = std::numeric_limits<int>::min();
116 BEAST_EXPECT(numberFromJson(sfNumber, imin) == STNumber(sfNumber, Number(imin, 0)));
117 BEAST_EXPECT(numberFromJson(sfNumber, std::to_string(imin)) == STNumber(sfNumber, Number(imin, 0)));
118
119 constexpr auto imax = std::numeric_limits<int>::max();
120 BEAST_EXPECT(numberFromJson(sfNumber, imax) == STNumber(sfNumber, Number(imax, 0)));
121 BEAST_EXPECT(numberFromJson(sfNumber, std::to_string(imax)) == STNumber(sfNumber, Number(imax, 0)));
122
123 constexpr auto umax = std::numeric_limits<unsigned int>::max();
124 BEAST_EXPECT(numberFromJson(sfNumber, umax) == STNumber(sfNumber, Number(umax, 0)));
125 BEAST_EXPECT(numberFromJson(sfNumber, std::to_string(umax)) == STNumber(sfNumber, Number(umax, 0)));
126
127 // Obvious non-numbers tested here
128 try
129 {
130 auto _ = numberFromJson(sfNumber, "");
131 BEAST_EXPECT(false);
132 }
133 catch (std::runtime_error const& e)
134 {
135 std::string const expected = "'' is not a number";
136 BEAST_EXPECT(e.what() == expected);
137 }
138
139 try
140 {
141 auto _ = numberFromJson(sfNumber, "e");
142 BEAST_EXPECT(false);
143 }
144 catch (std::runtime_error const& e)
145 {
146 std::string const expected = "'e' is not a number";
147 BEAST_EXPECT(e.what() == expected);
148 }
149
150 try
151 {
152 auto _ = numberFromJson(sfNumber, "1e");
153 BEAST_EXPECT(false);
154 }
155 catch (std::runtime_error const& e)
156 {
157 std::string const expected = "'1e' is not a number";
158 BEAST_EXPECT(e.what() == expected);
159 }
160
161 try
162 {
163 auto _ = numberFromJson(sfNumber, "e2");
164 BEAST_EXPECT(false);
165 }
166 catch (std::runtime_error const& e)
167 {
168 std::string const expected = "'e2' is not a number";
169 BEAST_EXPECT(e.what() == expected);
170 }
171
172 try
173 {
174 auto _ = numberFromJson(sfNumber, Json::Value());
175 BEAST_EXPECT(false);
176 }
177 catch (std::runtime_error const& e)
178 {
179 std::string const expected = "not a number";
180 BEAST_EXPECT(e.what() == expected);
181 }
182
183 try
184 {
185 auto _ = numberFromJson(
186 sfNumber,
187 "1234567890123456789012345678901234567890123456789012345678"
188 "9012345678901234567890123456789012345678901234567890123456"
189 "78901234567890123456789012345678901234567890");
190 BEAST_EXPECT(false);
191 }
192 catch (std::bad_cast const& e)
193 {
194 BEAST_EXPECT(true);
195 }
196
197 // We do not handle leading zeros
198 try
199 {
200 auto _ = numberFromJson(sfNumber, "001");
201 BEAST_EXPECT(false);
202 }
203 catch (std::runtime_error const& e)
204 {
205 std::string const expected = "'001' is not a number";
206 BEAST_EXPECT(e.what() == expected);
207 }
208
209 try
210 {
211 auto _ = numberFromJson(sfNumber, "000.0");
212 BEAST_EXPECT(false);
213 }
214 catch (std::runtime_error const& e)
215 {
216 std::string const expected = "'000.0' is not a number";
217 BEAST_EXPECT(e.what() == expected);
218 }
219
220 // We do not handle dangling dot
221 try
222 {
223 auto _ = numberFromJson(sfNumber, ".1");
224 BEAST_EXPECT(false);
225 }
226 catch (std::runtime_error const& e)
227 {
228 std::string const expected = "'.1' is not a number";
229 BEAST_EXPECT(e.what() == expected);
230 }
231
232 try
233 {
234 auto _ = numberFromJson(sfNumber, "1.");
235 BEAST_EXPECT(false);
236 }
237 catch (std::runtime_error const& e)
238 {
239 std::string const expected = "'1.' is not a number";
240 BEAST_EXPECT(e.what() == expected);
241 }
242
243 try
244 {
245 auto _ = numberFromJson(sfNumber, "1.e3");
246 BEAST_EXPECT(false);
247 }
248 catch (std::runtime_error const& e)
249 {
250 std::string const expected = "'1.e3' is not a number";
251 BEAST_EXPECT(e.what() == expected);
252 }
253 }
254 }
255
256 void
257 run() override
258 {
260
261 for (auto const scale : {MantissaRange::small, MantissaRange::large})
262 {
263 NumberMantissaScaleGuard sg(scale);
265 doRun();
266 }
267 }
268};
269
270BEAST_DEFINE_TESTSUITE(STNumber, protocol, xrpl);
271
272} // 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:147
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:800
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:454
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:597
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:3436
STNumber numberFromJson(SField const &field, Json::Value const &value)
Definition STNumber.cpp:205
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)