rippled
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 <ripple/beast/core/LexicalCast.h>
21 #include <ripple/beast/unit_test.h>
22 #include <ripple/beast/xor_shift_engine.h>
23 
24 namespace beast {
25 
26 class LexicalCast_test : public unit_test::suite
27 {
28 public:
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  {
40  std::string s;
41  IntType out(in + 1);
42 
43  expect(lexicalCastChecked(s, in));
44  expect(lexicalCastChecked(out, s));
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 
282  testPathologies();
286  testZero();
287  testEdgeCases();
288  testEntireRange();
289  }
290 };
291 
292 BEAST_DEFINE_TESTSUITE(LexicalCast, beast_core, beast);
293 
294 } // namespace beast
beast::LexicalCast_test::testInteger
void testInteger(IntType in)
Definition: LexicalCast_test.cpp:38
beast::LexicalCast_test::run
void run() override
Definition: LexicalCast_test.cpp:267
beast::LexicalCast_test
Definition: LexicalCast_test.cpp:26
std::string
STL class.
beast::LexicalCast_test::testConversionUnderflows
void testConversionUnderflows()
Definition: LexicalCast_test.cpp:107
beast::LexicalCast_test::testPathologies
void testPathologies()
Definition: LexicalCast_test.cpp:75
beast::LexicalCast_test::tryEdgeCase
bool tryEdgeCase(std::string const &s)
Definition: LexicalCast_test.cpp:120
beast::lexicalCast
Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
Definition: LexicalCast.h:296
std::stringstream
STL class.
beast::BadLexicalCast
Thrown when a conversion is not possible with LexicalCast.
Definition: LexicalCast.h:256
beast::LexicalCast_test::tryBadConvert
void tryBadConvert(std::string const &s)
Definition: LexicalCast_test.cpp:90
beast::LexicalCast_test::testEdgeCases
void testEdgeCases()
Definition: LexicalCast_test.cpp:133
beast::LexicalCast_test::testThrowingConversions
void testThrowingConversions()
Definition: LexicalCast_test.cpp:195
beast::LexicalCast_test::nextRandomInt
static IntType nextRandomInt(xor_shift_engine &r)
Definition: LexicalCast_test.cpp:31
beast::LexicalCast_test::testZero
void testZero()
Definition: LexicalCast_test.cpp:215
std::to_string
T to_string(T... args)
beast::LexicalCast_test::testThrowConvert
void testThrowConvert(std::string const &s, bool success)
Definition: LexicalCast_test.cpp:176
std::int32_t
std::numeric_limits::min
T min(T... args)
beast::lexicalCastChecked
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition: LexicalCast.h:266
beast::LexicalCast_test::testIntegers
void testIntegers(xor_shift_engine &r)
Definition: LexicalCast_test.cpp:50
std::stringstream::str
T str(T... args)
beast::LexicalCast_test::testConversionOverflows
void testConversionOverflows()
Definition: LexicalCast_test.cpp:97
beast::detail::xor_shift_engine
Definition: xor_shift_engine.h:32
beast::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(aged_set, container, beast)
beast::LexicalCast_test::testEntireRange
void testEntireRange()
Definition: LexicalCast_test.cpp:237
std::numeric_limits
beast
Definition: base_uint.h:641