rippled
Loading...
Searching...
No Matches
LexicalCast_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of Beast: https://github.com/vinniefalco/Beast
4 Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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/core/LexicalCast.h>
21#include <xrpl/beast/unit_test.h>
22#include <xrpl/beast/xor_shift_engine.h>
23
24namespace beast {
25
27{
28public:
29 template <class IntType>
30 static IntType
32 {
33 return static_cast<IntType>(r());
34 }
35
36 template <class IntType>
37 void
38 testInteger(IntType in)
39 {
41 IntType out(in + 1);
42
45 expect(out == in);
46 }
47
48 template <class IntType>
49 void
51 {
52 {
54 ss << "random " << typeid(IntType).name();
55 testcase(ss.str());
56
57 for (int i = 0; i < 1000; ++i)
58 {
59 IntType const value(nextRandomInt<IntType>(r));
60 testInteger(value);
61 }
62 }
63
64 {
66 ss << "numeric_limits <" << typeid(IntType).name() << ">";
67 testcase(ss.str());
68
71 }
72 }
73
74 void
76 {
77 testcase("pathologies");
78 try
79 {
80 lexicalCastThrow<int>("\xef\xbc\x91\xef\xbc\x90"); // utf-8 encoded
81 }
82 catch (BadLexicalCast const&)
83 {
84 pass();
85 }
86 }
87
88 template <class T>
89 void
91 {
92 T out;
93 expect(!lexicalCastChecked(out, s), s);
94 }
95
96 void
98 {
99 testcase("conversion overflows");
100
101 tryBadConvert<std::uint64_t>("99999999999999999999");
102 tryBadConvert<std::uint32_t>("4294967300");
103 tryBadConvert<std::uint16_t>("75821");
104 }
105
106 void
108 {
109 testcase("conversion underflows");
110
111 tryBadConvert<std::uint32_t>("-1");
112
113 tryBadConvert<std::int64_t>("-99999999999999999999");
114 tryBadConvert<std::int32_t>("-4294967300");
115 tryBadConvert<std::int16_t>("-75821");
116 }
117
118 template <class T>
119 bool
121 {
122 T ret;
123
124 bool const result = lexicalCastChecked(ret, s);
125
126 if (!result)
127 return false;
128
129 return s == std::to_string(ret);
130 }
131
132 void
134 {
135 testcase("conversion edge cases");
136
137 expect(tryEdgeCase<std::uint64_t>("18446744073709551614"));
138 expect(tryEdgeCase<std::uint64_t>("18446744073709551615"));
139 expect(!tryEdgeCase<std::uint64_t>("18446744073709551616"));
140
141 expect(tryEdgeCase<std::int64_t>("9223372036854775806"));
142 expect(tryEdgeCase<std::int64_t>("9223372036854775807"));
143 expect(!tryEdgeCase<std::int64_t>("9223372036854775808"));
144
145 expect(tryEdgeCase<std::int64_t>("-9223372036854775807"));
146 expect(tryEdgeCase<std::int64_t>("-9223372036854775808"));
147 expect(!tryEdgeCase<std::int64_t>("-9223372036854775809"));
148
149 expect(tryEdgeCase<std::uint32_t>("4294967294"));
150 expect(tryEdgeCase<std::uint32_t>("4294967295"));
151 expect(!tryEdgeCase<std::uint32_t>("4294967296"));
152
153 expect(tryEdgeCase<std::int32_t>("2147483646"));
154 expect(tryEdgeCase<std::int32_t>("2147483647"));
155 expect(!tryEdgeCase<std::int32_t>("2147483648"));
156
157 expect(tryEdgeCase<std::int32_t>("-2147483647"));
158 expect(tryEdgeCase<std::int32_t>("-2147483648"));
159 expect(!tryEdgeCase<std::int32_t>("-2147483649"));
160
161 expect(tryEdgeCase<std::uint16_t>("65534"));
162 expect(tryEdgeCase<std::uint16_t>("65535"));
163 expect(!tryEdgeCase<std::uint16_t>("65536"));
164
165 expect(tryEdgeCase<std::int16_t>("32766"));
166 expect(tryEdgeCase<std::int16_t>("32767"));
167 expect(!tryEdgeCase<std::int16_t>("32768"));
168
169 expect(tryEdgeCase<std::int16_t>("-32767"));
170 expect(tryEdgeCase<std::int16_t>("-32768"));
171 expect(!tryEdgeCase<std::int16_t>("-32769"));
172 }
173
174 template <class T>
175 void
176 testThrowConvert(std::string const& s, bool success)
177 {
178 bool result = !success;
179 T out;
180
181 try
182 {
183 out = lexicalCastThrow<T>(s);
184 result = true;
185 }
186 catch (BadLexicalCast const&)
187 {
188 result = false;
189 }
190
191 expect(result == success, s);
192 }
193
194 void
196 {
197 testcase("throwing conversion");
198
199 testThrowConvert<std::uint64_t>("99999999999999999999", false);
200 testThrowConvert<std::uint64_t>("9223372036854775806", true);
201
202 testThrowConvert<std::uint32_t>("4294967290", true);
203 testThrowConvert<std::uint32_t>("42949672900", false);
204 testThrowConvert<std::uint32_t>("429496729000", false);
205 testThrowConvert<std::uint32_t>("4294967290000", false);
206
207 testThrowConvert<std::int32_t>("5294967295", false);
208 testThrowConvert<std::int32_t>("-2147483644", true);
209
210 testThrowConvert<std::int16_t>("66666", false);
211 testThrowConvert<std::int16_t>("-5711", true);
212 }
213
214 void
216 {
217 testcase("zero conversion");
218
219 {
220 std::int32_t out;
221
222 expect(lexicalCastChecked(out, "-0"), "0");
223 expect(lexicalCastChecked(out, "0"), "0");
224 expect(lexicalCastChecked(out, "+0"), "0");
225 }
226
227 {
228 std::uint32_t out;
229
230 expect(!lexicalCastChecked(out, "-0"), "0");
231 expect(lexicalCastChecked(out, "0"), "0");
232 expect(lexicalCastChecked(out, "+0"), "0");
233 }
234 }
235
236 void
238 {
239 testcase("entire range");
240
242 std::string const empty("");
243
245 {
246 std::int16_t j = static_cast<std::int16_t>(i);
247
248 auto actual = std::to_string(j);
249
250 auto result = lexicalCast(j, empty);
251
252 expect(result == actual, actual + " (string to integer)");
253
254 if (result == actual)
255 {
256 auto number = lexicalCast<std::int16_t>(result);
257
258 if (number != j)
259 expect(false, actual + " (integer to string)");
260 }
261
262 i++;
263 }
264 }
265
266 void
267 run() override
268 {
269 std::int64_t const seedValue = 50;
270
271 xor_shift_engine r(seedValue);
272
273 testIntegers<int>(r);
274 testIntegers<unsigned int>(r);
275 testIntegers<short>(r);
276 testIntegers<unsigned short>(r);
277 testIntegers<std::int32_t>(r);
278 testIntegers<std::uint32_t>(r);
279 testIntegers<std::int64_t>(r);
280 testIntegers<std::uint64_t>(r);
281
286 testZero();
289 }
290};
291
292BEAST_DEFINE_TESTSUITE(LexicalCast, beast, beast);
293
294} // 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:55
void pass()
Record a successful test condition.
Definition suite.h:511
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:229
T min(T... args)
Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
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)