1//
2// NumberParserTest.cpp
3//
4// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "NumberParserTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/Exception.h"
15#include "Poco/Types.h"
16#include "Poco/Format.h"
17#include "Poco/NumericString.h"
18#include "Poco/MemoryStream.h"
19#include "Poco/Stopwatch.h"
20#include <iostream>
21#include <iomanip>
22#include <cstdio>
23
24
25using Poco::NumberParser;
26using Poco::NumberFormatter;
27using Poco::SyntaxException;
28using Poco::Int8;
29using Poco::UInt8;
30using Poco::Int16;
31using Poco::UInt16;
32using Poco::Int32;
33using Poco::UInt32;
34using Poco::Int64;
35using Poco::UInt64;
36using Poco::format;
37using Poco::decimalSeparator;
38using Poco::thousandSeparator;
39
40
41NumberParserTest::NumberParserTest(const std::string& rName): CppUnit::TestCase(rName)
42{
43}
44
45
46NumberParserTest::~NumberParserTest()
47{
48}
49
50
51void NumberParserTest::testParse()
52{
53 std::string sep(".,");
54
55 for (int i = 0; i < 2; ++i)
56 {
57 char ts = sep[i];
58
59 assertTrue (NumberParser::parse("123") == 123);
60 assertTrue (NumberParser::parse(format("123%c456", ts), ts) == 123456);
61 assertTrue (NumberParser::parse(format("1%c234%c567", ts, ts), ts) == 1234567);
62 }
63
64 assertTrue (NumberParser::parse("+123") == 123);
65 assertTrue (NumberParser::parse("-123") == -123);
66 assertTrue (NumberParser::parse("0") == 0);
67 assertTrue (NumberParser::parse("000") == 0);
68 assertTrue (NumberParser::parse("0123") == 123);
69 assertTrue (NumberParser::parse("+0123") == 123);
70 assertTrue (NumberParser::parse("-0123") == -123);
71 assertTrue (NumberParser::parseUnsigned("123") == 123);
72 assertTrue (NumberParser::parseHex("12AB") == 0x12ab);
73 assertTrue (NumberParser::parseHex("0x12AB") == 0x12ab);
74 assertTrue (NumberParser::parseHex("0X12AB") == 0x12ab);
75 assertTrue (NumberParser::parseHex("0x99a") == 0x99a);
76 assertTrue (NumberParser::parseHex("00") == 0);
77 assertTrue (NumberParser::parseOct("123") == 0123);
78 assertTrue (NumberParser::parseOct("0123") == 0123);
79 assertTrue (NumberParser::parseOct("0") == 0);
80 assertTrue (NumberParser::parseOct("000") == 0);
81
82 assertTrue (NumberParser::parseBool("0") == false);
83 assertTrue (NumberParser::parseBool("FALSE") == false);
84 assertTrue (NumberParser::parseBool("no") == false);
85 assertTrue (NumberParser::parseBool("1") == true);
86 assertTrue (NumberParser::parseBool("True") == true);
87 assertTrue (NumberParser::parseBool("YeS") == true);
88
89#if defined(POCO_HAVE_INT64)
90 assertTrue (NumberParser::parse64("123") == 123);
91 assertTrue (NumberParser::parse64("-123") == -123);
92 assertTrue (NumberParser::parse64("0123") == 123);
93 assertTrue (NumberParser::parse64("-0123") == -123);
94 assertTrue (NumberParser::parseUnsigned64("123") == 123);
95 assertTrue (NumberParser::parseHex64("12AB") == 0x12ab);
96 assertTrue (NumberParser::parseOct64("123") == 0123);
97 assertTrue (NumberParser::parseOct64("0123") == 0123);
98#endif
99
100#ifndef POCO_NO_FPENVIRONMENT
101 for (int i = 0; i < 2; ++i)
102 {
103 char ts = sep[i];
104 for (int j = 0; j < 2; ++j)
105 {
106 char dp = sep[j];
107 if (ts == dp) continue;
108
109 assertEqualDelta(1.0, NumberParser::parseFloat(format("1", dp), dp, ts), 0.01);
110 assertEqualDelta(0.0, NumberParser::parseFloat(format("0%c0", dp), dp, ts), 0.01);
111 assertEqualDelta(0., NumberParser::parseFloat(format("0%c0", dp), dp, ts), 0.01);
112 assertEqualDelta(.0, NumberParser::parseFloat(format("0%c0", dp), dp, ts), 0.01);
113 assertEqualDelta(12.34, NumberParser::parseFloat(format("12%c34", dp), dp, ts), 0.01);
114 assertEqualDelta(12.34, NumberParser::parseFloat(format("12%c34f", dp), dp, ts), 0.01);
115 assertEqualDelta(12.34, NumberParser::parseFloat(format("12%c34", dp), dp, ts), 0.01);
116 assertEqualDelta(-12.34, NumberParser::parseFloat(format("-12%c34", dp), dp, ts), 0.01);
117 assertEqualDelta(.34, NumberParser::parseFloat(format("%c34", dp), dp, ts), 0.01);
118 assertEqualDelta(-.34, NumberParser::parseFloat(format("-%c34", dp), dp, ts), 0.01);
119 assertEqualDelta(12., NumberParser::parseFloat(format("12%c", dp), dp, ts), 0.01);
120 assertEqualDelta(-12., NumberParser::parseFloat(format("-12%c", dp), dp, ts), 0.01);
121 assertEqualDelta(12, NumberParser::parseFloat("12", dp, ts), 0.01);
122 assertEqualDelta(-12, NumberParser::parseFloat("-12", dp, ts), 0.01);
123 assertEqualDelta(12.34, NumberParser::parseFloat(format("12%c3456789012345678901234567890", dp), dp, ts), 0.01);
124
125 assertEqualDelta(1234.3456789, NumberParser::parseFloat(format("1%c234%c3456789012345678901234567890", ts, dp), dp, ts), 0.00000001);
126 assertEqualDelta(12345.3456789, NumberParser::parseFloat(format("12%c345%c3456789012345678901234567890", ts, dp), dp, ts), 0.00000001);
127 assertEqualDelta(123456.3456789, NumberParser::parseFloat(format("123%c456%c3456789012345678901234567890", ts, dp), dp, ts), 0.00000001);
128 assertEqualDelta(1234567.3456789, NumberParser::parseFloat(format("1%c234%c567%c3456789012345678901234567890", ts, ts, dp), dp, ts), 0.00000001);
129 assertEqualDelta(12345678.3456789, NumberParser::parseFloat(format("12%c345%c678%c3456789012345678901234567890", ts, ts, dp), dp, ts), 0.00000001);
130 assertEqualDelta(123456789.3456789, NumberParser::parseFloat(format("123%c456%c789%c3456789012345678901234567890", ts, ts, dp), dp, ts), 0.00000001);
131
132 if ((std::numeric_limits<double>::max() / 10) < 1.23456e10)
133 fail ("test value larger than max value for this platform");
134 else
135 {
136 double d = 1.234e100;
137 assertEqualDelta(d, NumberParser::parseFloat(format("1%c234e100", dp), dp, ts), 0.01);
138 assertEqualDelta(d, NumberParser::parseFloat(format("1%c234E+100", dp), dp, ts), 0.01);
139
140 d = 1.234e-100;
141 assertEqualDelta(d, NumberParser::parseFloat(format("1%c234E-100", dp), dp, ts), 0.01);
142
143 d = -1.234e100;
144 assertEqualDelta(d, NumberParser::parseFloat(format("-1%c234e+100", dp), dp, ts), 0.01);
145 assertEqualDelta(d, NumberParser::parseFloat(format("-1%c234E100", dp), dp, ts), 0.01);
146
147 d = 1234.234e-100;
148 assertEqualDelta(d, NumberParser::parseFloat(format("1%c234%c234e-100", ts, dp), dp, ts), 0.01);
149 d = 12345.234e-100;
150 assertEqualDelta(d, NumberParser::parseFloat(format("12%c345%c234e-100", ts, dp), dp, ts), 0.01);
151 d = 123456.234e-100;
152 assertEqualDelta(d, NumberParser::parseFloat(format("123%c456%c234e-100", ts, dp), dp, ts), 0.01);
153
154 d = -1234.234e-100;
155 assertEqualDelta(d, NumberParser::parseFloat(format("-1%c234%c234e-100", ts, dp), dp, ts), 0.01);
156 d = -12345.234e-100;
157 assertEqualDelta(d, NumberParser::parseFloat(format("-12%c345%c234e-100", ts, dp), dp, ts), 0.01);
158 d = -123456.234e-100;
159 assertEqualDelta(d, NumberParser::parseFloat(format("-123%c456%c234e-100", ts, dp), dp, ts), 0.01);
160 }
161
162 double d = 12.34e-10;
163 assertEqualDelta(d, NumberParser::parseFloat(format("12%c34e-10", dp), dp, ts), 0.01);
164 assertEqualDelta(-12.34, NumberParser::parseFloat(format("-12%c34", dp), dp, ts), 0.01);
165
166 assertEqualDelta(12.34, NumberParser::parseFloat(format("12%c34", dp), dp, ts), 0.01);
167 }
168 }
169#endif // POCO_NO_FPENVIRONMENT
170}
171
172
173void NumberParserTest::testLimits()
174{
175 assertTrue (testUpperLimit<Int8>());
176 assertTrue (testLowerLimit<Int8>());
177 assertTrue (testUpperLimit<UInt8>());
178 assertTrue (testUpperLimit<Int16>());
179 assertTrue (testLowerLimit<Int16>());
180 assertTrue (testUpperLimit<UInt16>());
181 assertTrue (testUpperLimit<Int32>());
182 assertTrue (testLowerLimit<Int32>());
183 assertTrue (testUpperLimit<UInt32>());
184 assertTrue (testUpperLimit64<Int64>());
185 assertTrue (testLowerLimit64<Int64>());
186 assertTrue (testUpperLimit64<UInt64>());
187}
188
189
190void NumberParserTest::testParseError()
191{
192 char dp = decimalSeparator();
193 if (dp == 0) dp = '.';
194 char ts = thousandSeparator();
195 if (ts == 0) ts = ',';
196 assertTrue (dp != ts);
197
198 try
199 {
200 NumberParser::parse("");
201 NumberParser::parseBool("");
202 failmsg("must throw SyntaxException");
203 } catch (SyntaxException&) { }
204
205 try
206 {
207 NumberParser::parse(" ");
208 NumberParser::parseBool("");
209 failmsg("must throw SyntaxException");
210 } catch (SyntaxException&) { }
211
212 try
213 {
214 NumberParser::parse(" 123");
215 NumberParser::parseBool("");
216 failmsg("must throw SyntaxException");
217 } catch (SyntaxException&) { }
218
219 try
220 {
221 NumberParser::parse("1 1");
222 NumberParser::parseBool("");
223 failmsg("must throw SyntaxException");
224 } catch (SyntaxException&) { }
225
226 try
227 {
228 NumberParser::parse("asd");
229 NumberParser::parseBool("asd");
230 failmsg("must throw SyntaxException");
231 } catch (SyntaxException&) { }
232
233 try
234 {
235 NumberParser::parseUnsigned("a123");
236 failmsg("must throw SyntaxException");
237 } catch (SyntaxException&) { }
238
239 try
240 {
241 NumberParser::parseUnsigned("-123");
242 failmsg("must throw SyntaxException");
243 } catch (SyntaxException&) { }
244
245 try
246 {
247 NumberParser::parseHex("z23");
248 failmsg("must throw SyntaxException");
249 } catch (SyntaxException&) { }
250
251 try
252 {
253 NumberParser::parseHex("23z");
254 failmsg("must throw SyntaxException");
255 } catch (SyntaxException&) { }
256
257 try
258 {
259 NumberParser::parseHex("xxx");
260 failmsg("must throw SyntaxException");
261 }
262 catch (SyntaxException&) {}
263
264#if defined(POCO_HAVE_INT64)
265
266 try
267 {
268 NumberParser::parse64("asd");
269 failmsg("must throw SyntaxException");
270 } catch (SyntaxException&) { }
271
272 try
273 {
274 NumberParser::parseUnsigned64("");
275 failmsg("must throw SyntaxException");
276 } catch (SyntaxException&) { }
277
278 try
279 {
280 NumberParser::parseHex64("zaz");
281 failmsg("must throw SyntaxException");
282 } catch (SyntaxException&) { }
283
284 try
285 {
286 NumberParser::parseHex64("12345z");
287 failmsg("must throw SyntaxException");
288 } catch (SyntaxException&) { }
289
290 try
291 {
292 NumberParser::parseHex64(format("123%c45", ts));
293 failmsg("must throw SyntaxException");
294 } catch (SyntaxException&) { }
295
296#endif // POCO_HAVE_INT64
297
298#ifndef POCO_NO_FPENVIRONMENT
299 try
300 {
301 NumberParser::parseFloat(format("a12%c3", dp));
302 failmsg("must throw SyntaxException");
303 } catch (SyntaxException&) { }
304
305#endif // POCO_NO_FPENVIRONMENT
306}
307
308
309void NumberParserTest::setUp()
310{
311}
312
313
314void NumberParserTest::tearDown()
315{
316}
317
318
319CppUnit::Test* NumberParserTest::suite()
320{
321 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NumberParserTest");
322
323 CppUnit_addTest(pSuite, NumberParserTest, testParse);
324 CppUnit_addTest(pSuite, NumberParserTest, testLimits);
325 CppUnit_addTest(pSuite, NumberParserTest, testParseError);
326
327 return pSuite;
328}
329