rippled
Loading...
Searching...
No Matches
STNumber_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2024 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpl/beast/unit_test.h>
21#include <xrpl/beast/unit_test/suite.h>
22#include <xrpl/json/json_forwards.h>
23#include <xrpl/protocol/Issue.h>
24#include <xrpl/protocol/STAmount.h>
25#include <xrpl/protocol/STNumber.h>
26
27#include <limits>
28#include <ostream>
29#include <stdexcept>
30
31namespace ripple {
32
34{
35 void
37 {
38 STNumber const before{sfNumber, number};
39 BEAST_EXPECT(number == before);
40 Serializer s;
41 before.add(s);
42 BEAST_EXPECT(s.size() == 12);
43 SerialIter sit(s.slice());
44 STNumber const after{sit, sfNumber};
45 BEAST_EXPECT(after.isEquivalent(before));
46 BEAST_EXPECT(number == after);
47 }
48
49 void
50 run() override
51 {
53
54 {
55 STNumber const stnum{sfNumber};
56 BEAST_EXPECT(stnum.getSType() == STI_NUMBER);
57 BEAST_EXPECT(stnum.getText() == "0");
58 BEAST_EXPECT(stnum.isDefault() == true);
59 BEAST_EXPECT(stnum.value() == Number{0});
60 }
61
62 std::initializer_list<std::int64_t> const mantissas = {
64 -1,
65 0,
66 1,
68 for (std::int64_t mantissa : mantissas)
69 testCombo(Number{mantissa});
70
71 std::initializer_list<std::int32_t> const exponents = {
73 for (std::int32_t exponent : exponents)
74 testCombo(Number{123, exponent});
75
76 {
77 STAmount const strikePrice{noIssue(), 100};
78 STNumber const factor{sfNumber, 100};
79 auto const iouValue = strikePrice.iou();
80 IOUAmount totalValue{iouValue * factor};
81 STAmount const totalAmount{totalValue, strikePrice.issue()};
82 BEAST_EXPECT(totalAmount == Number{10'000});
83 }
84
85 {
86 BEAST_EXPECT(
87 numberFromJson(sfNumber, Json::Value(42)) ==
88 STNumber(sfNumber, 42));
89 BEAST_EXPECT(
90 numberFromJson(sfNumber, Json::Value(-42)) ==
91 STNumber(sfNumber, -42));
92
93 BEAST_EXPECT(
94 numberFromJson(sfNumber, Json::UInt(42)) ==
95 STNumber(sfNumber, 42));
96
97 BEAST_EXPECT(
98 numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
99
100 BEAST_EXPECT(
101 numberFromJson(sfNumber, "123") == STNumber(sfNumber, 123));
102 BEAST_EXPECT(
103 numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123));
104
105 BEAST_EXPECT(
106 numberFromJson(sfNumber, "3.14") ==
107 STNumber(sfNumber, Number(314, -2)));
108 BEAST_EXPECT(
109 numberFromJson(sfNumber, "-3.14") ==
110 STNumber(sfNumber, -Number(314, -2)));
111 BEAST_EXPECT(
112 numberFromJson(sfNumber, "3.14e2") == STNumber(sfNumber, 314));
113 BEAST_EXPECT(
114 numberFromJson(sfNumber, "-3.14e2") ==
115 STNumber(sfNumber, -314));
116
117 BEAST_EXPECT(
118 numberFromJson(sfNumber, "1000e-2") == STNumber(sfNumber, 10));
119 BEAST_EXPECT(
120 numberFromJson(sfNumber, "-1000e-2") ==
121 STNumber(sfNumber, -10));
122
123 BEAST_EXPECT(
124 numberFromJson(sfNumber, "0") == STNumber(sfNumber, 0));
125 BEAST_EXPECT(
126 numberFromJson(sfNumber, "0.0") == STNumber(sfNumber, 0));
127 BEAST_EXPECT(
128 numberFromJson(sfNumber, "0.000") == STNumber(sfNumber, 0));
129 BEAST_EXPECT(
130 numberFromJson(sfNumber, "-0") == STNumber(sfNumber, 0));
131 BEAST_EXPECT(
132 numberFromJson(sfNumber, "-0.0") == STNumber(sfNumber, 0));
133 BEAST_EXPECT(
134 numberFromJson(sfNumber, "-0.000") == STNumber(sfNumber, 0));
135 BEAST_EXPECT(
136 numberFromJson(sfNumber, "0e6") == STNumber(sfNumber, 0));
137 BEAST_EXPECT(
138 numberFromJson(sfNumber, "0.0e6") == STNumber(sfNumber, 0));
139 BEAST_EXPECT(
140 numberFromJson(sfNumber, "0.000e6") == STNumber(sfNumber, 0));
141 BEAST_EXPECT(
142 numberFromJson(sfNumber, "-0e6") == STNumber(sfNumber, 0));
143 BEAST_EXPECT(
144 numberFromJson(sfNumber, "-0.0e6") == STNumber(sfNumber, 0));
145 BEAST_EXPECT(
146 numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0));
147
148 // Obvious non-numbers tested here
149 try
150 {
151 auto _ = numberFromJson(sfNumber, "");
152 BEAST_EXPECT(false);
153 }
154 catch (std::runtime_error const& e)
155 {
156 std::string const expected = "'' is not a number";
157 BEAST_EXPECT(e.what() == expected);
158 }
159
160 try
161 {
162 auto _ = numberFromJson(sfNumber, "e");
163 BEAST_EXPECT(false);
164 }
165 catch (std::runtime_error const& e)
166 {
167 std::string const expected = "'e' is not a number";
168 BEAST_EXPECT(e.what() == expected);
169 }
170
171 try
172 {
173 auto _ = numberFromJson(sfNumber, "1e");
174 BEAST_EXPECT(false);
175 }
176 catch (std::runtime_error const& e)
177 {
178 std::string const expected = "'1e' is not a number";
179 BEAST_EXPECT(e.what() == expected);
180 }
181
182 try
183 {
184 auto _ = numberFromJson(sfNumber, "e2");
185 BEAST_EXPECT(false);
186 }
187 catch (std::runtime_error const& e)
188 {
189 std::string const expected = "'e2' is not a number";
190 BEAST_EXPECT(e.what() == expected);
191 }
192
193 try
194 {
195 auto _ = numberFromJson(sfNumber, Json::Value());
196 BEAST_EXPECT(false);
197 }
198 catch (std::runtime_error const& e)
199 {
200 std::string const expected = "not a number";
201 BEAST_EXPECT(e.what() == expected);
202 }
203
204 try
205 {
206 auto _ = numberFromJson(
207 sfNumber,
208 "1234567890123456789012345678901234567890123456789012345678"
209 "9012345678901234567890123456789012345678901234567890123456"
210 "78901234567890123456789012345678901234567890");
211 BEAST_EXPECT(false);
212 }
213 catch (std::bad_cast const& e)
214 {
215 BEAST_EXPECT(true);
216 }
217
218 // We do not handle leading zeros
219 try
220 {
221 auto _ = numberFromJson(sfNumber, "001");
222 BEAST_EXPECT(false);
223 }
224 catch (std::runtime_error const& e)
225 {
226 std::string const expected = "'001' is not a number";
227 BEAST_EXPECT(e.what() == expected);
228 }
229
230 try
231 {
232 auto _ = numberFromJson(sfNumber, "000.0");
233 BEAST_EXPECT(false);
234 }
235 catch (std::runtime_error const& e)
236 {
237 std::string const expected = "'000.0' is not a number";
238 BEAST_EXPECT(e.what() == expected);
239 }
240
241 // We do not handle dangling dot
242 try
243 {
244 auto _ = numberFromJson(sfNumber, ".1");
245 BEAST_EXPECT(false);
246 }
247 catch (std::runtime_error const& e)
248 {
249 std::string const expected = "'.1' is not a number";
250 BEAST_EXPECT(e.what() == expected);
251 }
252
253 try
254 {
255 auto _ = numberFromJson(sfNumber, "1.");
256 BEAST_EXPECT(false);
257 }
258 catch (std::runtime_error const& e)
259 {
260 std::string const expected = "'1.' is not a number";
261 BEAST_EXPECT(e.what() == expected);
262 }
263
264 try
265 {
266 auto _ = numberFromJson(sfNumber, "1.e3");
267 BEAST_EXPECT(false);
268 }
269 catch (std::runtime_error const& e)
270 {
271 std::string const expected = "'1.e3' is not a number";
272 BEAST_EXPECT(e.what() == expected);
273 }
274 }
275 }
276};
277
278BEAST_DEFINE_TESTSUITE(STNumber, protocol, ripple);
279
280void
282{
283 STNumber number{sfNumber, 42};
284 out << number;
285}
286
287} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
A testsuite class.
Definition suite.h:55
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:46
static constexpr int maxExponent
Definition Number.h:48
static constexpr int minExponent
Definition Number.h:47
Issue const & issue() const
Definition STAmount.h:496
A serializable number.
Definition STNumber.h:43
std::size_t size() const noexcept
Definition Serializer.h:72
Slice slice() const noexcept
Definition Serializer.h:66
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:25
void testCompile(std::ostream &out)
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
Definition Issue.h:123
STNumber numberFromJson(SField const &field, Json::Value const &value)
Definition STNumber.cpp:179
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:3266
void testCombo(Number number)
void run() override
Runs the suite.
T what(T... args)