xrpld
Loading...
Searching...
No Matches
LexicalCast_test.cpp
1#include <xrpl/beast/core/LexicalCast.h>
2#include <xrpl/beast/unit_test/suite.h>
3#include <xrpl/beast/xor_shift_engine.h>
4
5#include <cstdint>
6#include <limits>
7#include <sstream>
8#include <string>
9
10namespace beast {
11
13{
14public:
15 template <class IntType>
16 static IntType
18 {
19 return static_cast<IntType>(r());
20 }
21
22 template <class IntType>
23 void
24 testInteger(IntType in)
25 {
27 IntType out = static_cast<IntType>(~in); // Ensure out != in
28
31 expect(out == in);
32 }
33
34 template <class IntType>
35 void
37 {
38 {
40 ss << "random " << typeid(IntType).name();
41 testcase(ss.str());
42
43 for (int i = 0; i < 1000; ++i)
44 {
45 IntType const value(nextRandomInt<IntType>(r));
46 testInteger(value);
47 }
48 }
49
50 {
52 ss << "numeric_limits <" << typeid(IntType).name() << ">";
53 testcase(ss.str());
54
57 }
58 }
59
60 void
62 {
63 testcase("pathologies");
64 try
65 {
66 lexicalCastThrow<int>("\xef\xbc\x91\xef\xbc\x90"); // utf-8 encoded
67 }
68 catch (BadLexicalCast const&)
69 {
70 pass();
71 }
72 }
73
74 template <class T>
75 void
77 {
78 T out;
79 expect(!lexicalCastChecked(out, s), s);
80 }
81
82 void
84 {
85 testcase("conversion overflows");
86
87 tryBadConvert<std::uint64_t>("99999999999999999999");
88 tryBadConvert<std::uint32_t>("4294967300");
90 }
91
92 void
94 {
95 testcase("conversion underflows");
96
98
99 tryBadConvert<std::int64_t>("-99999999999999999999");
100 tryBadConvert<std::int32_t>("-4294967300");
102 }
103
104 template <class T>
105 bool
107 {
108 T ret;
109
110 bool const result = lexicalCastChecked(ret, s);
111
112 if (!result)
113 return false;
114
115 return s == std::to_string(ret);
116 }
117
118 void
120 {
121 testcase("conversion edge cases");
122
123 expect(tryEdgeCase<std::uint64_t>("18446744073709551614"));
124 expect(tryEdgeCase<std::uint64_t>("18446744073709551615"));
125 expect(!tryEdgeCase<std::uint64_t>("18446744073709551616"));
126
127 expect(tryEdgeCase<std::int64_t>("9223372036854775806"));
128 expect(tryEdgeCase<std::int64_t>("9223372036854775807"));
129 expect(!tryEdgeCase<std::int64_t>("9223372036854775808"));
130
131 expect(tryEdgeCase<std::int64_t>("-9223372036854775807"));
132 expect(tryEdgeCase<std::int64_t>("-9223372036854775808"));
133 expect(!tryEdgeCase<std::int64_t>("-9223372036854775809"));
134
135 expect(tryEdgeCase<std::uint32_t>("4294967294"));
136 expect(tryEdgeCase<std::uint32_t>("4294967295"));
137 expect(!tryEdgeCase<std::uint32_t>("4294967296"));
138
139 expect(tryEdgeCase<std::int32_t>("2147483646"));
140 expect(tryEdgeCase<std::int32_t>("2147483647"));
141 expect(!tryEdgeCase<std::int32_t>("2147483648"));
142
143 expect(tryEdgeCase<std::int32_t>("-2147483647"));
144 expect(tryEdgeCase<std::int32_t>("-2147483648"));
145 expect(!tryEdgeCase<std::int32_t>("-2147483649"));
146
150
154
158 }
159
160 template <class T>
161 void
162 testThrowConvert(std::string const& s, bool success)
163 {
164 bool result = !success;
165 T out;
166
167 try
168 {
169 out = lexicalCastThrow<T>(s);
170 result = true;
171 }
172 catch (BadLexicalCast const&)
173 {
174 result = false;
175 }
176
177 expect(result == success, s);
178 }
179
180 void
182 {
183 testcase("throwing conversion");
184
185 testThrowConvert<std::uint64_t>("99999999999999999999", false);
186 testThrowConvert<std::uint64_t>("9223372036854775806", true);
187
188 testThrowConvert<std::uint32_t>("4294967290", true);
189 testThrowConvert<std::uint32_t>("42949672900", false);
190 testThrowConvert<std::uint32_t>("429496729000", false);
191 testThrowConvert<std::uint32_t>("4294967290000", false);
192
193 testThrowConvert<std::int32_t>("5294967295", false);
194 testThrowConvert<std::int32_t>("-2147483644", true);
195
196 testThrowConvert<std::int16_t>("66666", false);
197 testThrowConvert<std::int16_t>("-5711", true);
198 }
199
200 void
202 {
203 testcase("zero conversion");
204
205 {
206 std::int32_t out = 0;
207
208 expect(lexicalCastChecked(out, "-0"), "0");
209 expect(lexicalCastChecked(out, "0"), "0");
210 expect(lexicalCastChecked(out, "+0"), "0");
211 }
212
213 {
214 std::uint32_t out = 0;
215
216 expect(!lexicalCastChecked(out, "-0"), "0");
217 expect(lexicalCastChecked(out, "0"), "0");
218 expect(lexicalCastChecked(out, "+0"), "0");
219 }
220 }
221
222 void
224 {
225 testcase("entire range");
226
228 std::string const empty;
229
231 {
232 std::int16_t const j = static_cast<std::int16_t>(i);
233
234 auto actual = std::to_string(j);
235
236 auto result = lexicalCast(j, empty);
237
238 expect(result == actual, actual + " (string to integer)");
239
240 if (result == actual)
241 {
242 auto number = lexicalCast<std::int16_t>(result);
243
244 if (number != j)
245 expect(false, actual + " (integer to string)");
246 }
247
248 i++;
249 }
250 }
251
252 void
276};
277
279
280} // namespace beast
static IntType nextRandomInt(xor_shift_engine &r)
void testIntegers(xor_shift_engine &r)
void run() override
Runs the suite.
bool tryEdgeCase(std::string const &s)
void testThrowConvert(std::string const &s, bool success)
void tryBadConvert(std::string const &s)
A testsuite class.
Definition suite.h:50
void pass()
Record a successful test condition.
Definition suite.h:500
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:223
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
T max(T... args)
T min(T... args)
Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
detail::XorShiftEngine<> xor_shift_engine
XOR-shift Generator.
Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
BEAST_DEFINE_TESTSUITE(aged_set, beast, beast)
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
T str(T... args)
Thrown when a conversion is not possible with LexicalCast.
T to_string(T... args)