mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
stringUtils_test.cpp
Go to the documentation of this file.
1/** \file stringUtils_test.cpp
2 */
3#include "../../catch2/catch.hpp"
4
5#define MX_NO_ERROR_REPORTS
6
7#include "../../../include/ioutils/stringUtils.hpp"
8
9#include <cmath>
10
11using namespace Catch::Matchers;
12
13using namespace mx::ioutils;
14using namespace mx;
15
16namespace unitTest
17{
18namespace ioutilsTest
19{
20namespace stringUtilsTest
21{
22
23/// Converting strings to numbers
24/**
25 * \ingroup stringUtils_unit_tests
26 */
27TEST_CASE( "Converting strings to numbers", "[ioutils::stringUtils]" )
28{
29 SECTION( "a string char" )
30 {
31 SECTION( "string valid, positive, no error check" )
32 {
33 char val = stoT<char>( "5" );
34 REQUIRE( static_cast<int>( val ) == 5 );
35 }
36
37 SECTION( "string valid, negative, w/ error check" )
38 {
39 mx::error_t errc;
40 char val = stoT<char>( "-5", &errc );
41 REQUIRE( static_cast<int>( val ) == -5 );
42 REQUIRE( errc == mx::error_t::noerror );
43 }
44
45 SECTION( "positive overflow, w/ error check" )
46 {
47 mx::error_t errc;
48 char val = stoT<char>( "128", &errc );
49 REQUIRE( static_cast<int>( val ) == std::numeric_limits<char>::max() );
50 REQUIRE( errc == mx::error_t::erange );
51 }
52
53 SECTION( "negative overflow, w/ error check" )
54 {
55 mx::error_t errc;
56 char val = stoT<char>( "-129", &errc );
57 REQUIRE( static_cast<int>( val ) == std::numeric_limits<char>::lowest() );
58 REQUIRE( errc == mx::error_t::erange );
59 }
60
61 SECTION( "invalid string, w/ error check" )
62 {
63 mx::error_t errc;
64 char val = stoT<char>( "!", &errc );
65 REQUIRE( static_cast<int>( val ) == 0 );
66 REQUIRE( errc == mx::error_t::invalidarg );
67 }
68
69 SECTION( "string valid w/ leading spaces, negative, w/ error check" )
70 {
71 mx::error_t errc;
72 char val = stoT<char>( " -5", &errc );
73 REQUIRE( static_cast<int>( val ) == -5 );
74 REQUIRE( errc == mx::error_t::noerror );
75 }
76 }
77
78 SECTION( "a string unsigned char" )
79 {
80 SECTION( "string valid, positive, no error check" )
81 {
82 unsigned char val = stoT<unsigned char>( "200" );
83 REQUIRE( static_cast<int>( val ) == 200 );
84 }
85
86 SECTION( "string valid, w/ error check" )
87 {
88 mx::error_t errc;
89 unsigned char val = stoT<unsigned char>( "100", &errc );
90 REQUIRE( static_cast<int>( val ) == 100 );
91 REQUIRE( errc == mx::error_t::noerror );
92 }
93
94 SECTION( "positive overflow, w/ error check" )
95 {
96 mx::error_t errc;
97 unsigned char val = stoT<unsigned char>( "256", &errc );
98 REQUIRE( static_cast<int>( val ) == std::numeric_limits<unsigned char>::max() );
99 REQUIRE( errc == mx::error_t::erange );
100 }
101
102 SECTION( "invalid string, w/ error check" )
103 {
104 mx::error_t errc;
105 unsigned char val = stoT<unsigned char>( "*", &errc );
106 REQUIRE( static_cast<int>( val ) == 0 );
107 REQUIRE( errc == mx::error_t::invalidarg );
108 }
109 }
110
111 SECTION( "a string short" )
112 {
113 SECTION( "string valid, positive, no error check" )
114 {
115 short val = stoT<short>( "500" );
116 REQUIRE( static_cast<int>( val ) == 500 );
117 }
118
119 SECTION( "string valid, negative, w/ error check" )
120 {
121 mx::error_t errc;
122 short val = stoT<short>( "-1024", &errc );
123 REQUIRE( static_cast<int>( val ) == -1024 );
124 REQUIRE( errc == mx::error_t::noerror );
125 }
126
127 SECTION( "positive overflow, w/ error check" )
128 {
129 mx::error_t errc;
130 short val = stoT<short>( "47000", &errc );
131 REQUIRE( static_cast<int>( val ) == std::numeric_limits<short>::max() );
132 REQUIRE( errc == mx::error_t::erange );
133 }
134
135 SECTION( "negative overflow, w/ error check" )
136 {
137 mx::error_t errc;
138 short val = stoT<short>( "-37000", &errc );
139 REQUIRE( static_cast<int>( val ) == std::numeric_limits<short>::lowest() );
140 REQUIRE( errc == mx::error_t::erange );
141 }
142
143 SECTION( "invalid string, w/ error check" )
144 {
145 mx::error_t errc;
146 short val = stoT<short>( "-", &errc );
147 REQUIRE( static_cast<int>( val ) == 0 );
148 REQUIRE( errc == mx::error_t::invalidarg );
149 }
150 }
151
152 SECTION( "a string unsigned short" )
153 {
154 SECTION( "string valid, positive, no error check" )
155 {
156 unsigned short val = stoT<unsigned short>( "20000" );
157 REQUIRE( static_cast<int>( val ) == 20000 );
158 }
159
160 SECTION( "string valid, w/ error check" )
161 {
162 mx::error_t errc;
163 unsigned short val = stoT<unsigned short>( "65000", &errc );
164 REQUIRE( static_cast<int>( val ) == 65000 );
165 REQUIRE( errc == mx::error_t::noerror );
166 }
167
168 SECTION( "positive overflow, w/ error check" )
169 {
170 mx::error_t errc;
171 unsigned short val = stoT<unsigned short>( "70000", &errc );
172 REQUIRE( static_cast<int>( val ) == std::numeric_limits<unsigned short>::max() );
173 REQUIRE( errc == mx::error_t::erange );
174 }
175
176 SECTION( "invalid string, w/ error check" )
177 {
178 mx::error_t errc;
179 unsigned short val = stoT<unsigned short>( "#", &errc );
180 REQUIRE( static_cast<int>( val ) == 0 );
181 REQUIRE( errc == mx::error_t::invalidarg );
182 }
183 }
184
185 SECTION( "a string int" )
186 {
187 SECTION( "string valid, positive, no error check" )
188 {
189 int val = stoT<int>( "1000000" );
190 REQUIRE( static_cast<int>( val ) == 1000000 );
191 }
192
193 SECTION( "string valid, negative, w/ error check" )
194 {
195 mx::error_t errc;
196 int val = stoT<int>( "-2000000", &errc );
197 REQUIRE( static_cast<int>( val ) == -2000000 );
198 REQUIRE( errc == mx::error_t::noerror );
199 }
200
201 SECTION( "positive overflow, w/ error check" )
202 {
203 mx::error_t errc;
204 int val = stoT<int>( "3000000000", &errc );
205 REQUIRE( static_cast<int>( val ) == std::numeric_limits<int>::max() );
206 REQUIRE( errc == mx::error_t::erange );
207 }
208
209 SECTION( "negative overflow, w/ error check" )
210 {
211 mx::error_t errc;
212 int val = stoT<int>( "-2147483650", &errc );
213 REQUIRE( static_cast<int>( val ) == std::numeric_limits<int>::lowest() );
214 REQUIRE( errc == mx::error_t::erange );
215 }
216
217 SECTION( "invalid string, w/ error check" )
218 {
219 mx::error_t errc;
220 int val = stoT<int>( " w", &errc );
221 REQUIRE( static_cast<int>( val ) == 0 );
222 REQUIRE( errc == mx::error_t::invalidarg );
223 }
224 }
225
226 SECTION( "a string unsigned int" )
227 {
228 SECTION( "string valid, positive, no error check" )
229 {
230 unsigned int val = stoT<unsigned int>( "4000000000" );
231 REQUIRE( static_cast<unsigned int>( val ) == 4000000000 );
232 }
233
234 SECTION( "string valid, w/ error check" )
235 {
236 mx::error_t errc;
237 unsigned int val = stoT<unsigned int>( "2", &errc );
238 REQUIRE( static_cast<unsigned int>( val ) == 2 );
239 REQUIRE( errc == mx::error_t::noerror );
240 }
241
242 SECTION( "positive overflow, w/ error check" )
243 {
244 mx::error_t errc;
245 unsigned int val = stoT<unsigned int>( "6000000000", &errc );
246 REQUIRE( static_cast<unsigned int>( val ) == std::numeric_limits<unsigned int>::max() );
247 REQUIRE( errc == mx::error_t::erange );
248 }
249
250 SECTION( "invalid string, w/ error check" )
251 {
252 mx::error_t errc;
253 unsigned int val = stoT<unsigned int>( "?8", &errc );
254 REQUIRE( static_cast<unsigned int>( val ) == 0 );
255 REQUIRE( errc == mx::error_t::invalidarg );
256 }
257 }
258
259 SECTION( "a string long" )
260 {
261 SECTION( "string valid, positive, no error check" )
262 {
263 long val = stoT<long>( "1000000" );
264 REQUIRE( static_cast<long>( val ) == 1000000 );
265 }
266
267 SECTION( "string valid, negative, w/ error check" )
268 {
269 mx::error_t errc;
270 long val = stoT<long>( "-2000000", &errc );
271 REQUIRE( static_cast<long>( val ) == -2000000 );
272 REQUIRE( errc == mx::error_t::noerror );
273 }
274
275 SECTION( "positive overflow, w/ error check" )
276 {
277 mx::error_t errc;
278 long val = stoT<long>( "9223372036854775808", &errc );
279 REQUIRE( static_cast<long>( val ) == std::numeric_limits<long>::max() );
280 REQUIRE( errc == mx::error_t::erange );
281 }
282
283 SECTION( "negative overflow, w/ error check" )
284 {
285 mx::error_t errc;
286 long val = stoT<long>( "-9223372036854775809", &errc );
287 REQUIRE( static_cast<long>( val ) == std::numeric_limits<long>::lowest() );
288 REQUIRE( errc == mx::error_t::erange );
289 }
290
291 SECTION( "invalid string, w/ error check" )
292 {
293 mx::error_t errc;
294 long val = stoT<long>( " w8", &errc );
295 REQUIRE( static_cast<long>( val ) == 0 );
296 REQUIRE( errc == mx::error_t::invalidarg );
297 }
298 }
299
300 SECTION( "a string unsigned long" )
301 {
302 SECTION( "string valid, positive, no error check" )
303 {
304 unsigned long val = stoT<unsigned long>( "400000000000" );
305 REQUIRE( static_cast<unsigned long>( val ) == 400000000000 );
306 }
307
308 SECTION( "string valid, w/ error check" )
309 {
310 mx::error_t errc;
311 unsigned long val = stoT<unsigned long>( "16", &errc );
312 REQUIRE( static_cast<unsigned long>( val ) == 16 );
313 REQUIRE( errc == mx::error_t::noerror );
314 }
315
316 SECTION( "positive overflow, w/ error check" )
317 {
318 mx::error_t errc;
319 unsigned long val = stoT<unsigned long>( "18523372036854775808", &errc );
320 REQUIRE( static_cast<unsigned long>( val ) == std::numeric_limits<unsigned long>::max() );
321 REQUIRE( errc == mx::error_t::erange );
322 }
323
324 SECTION( "invalid string, w/ error check" )
325 {
326 mx::error_t errc;
327 unsigned long val = stoT<unsigned long>( "?8", &errc );
328 REQUIRE( static_cast<unsigned long>( val ) == 0 );
329 REQUIRE( errc == mx::error_t::invalidarg );
330 }
331 }
332
333 SECTION( "a string long long" )
334 {
335 SECTION( "string valid, positive, no error check" )
336 {
337 long long val = stoT<long long>( "1000052" );
338 REQUIRE( static_cast<long long>( val ) == 1000052 );
339 }
340
341 SECTION( "string valid, negative, w/ error check" )
342 {
343 mx::error_t errc;
344 long long val = stoT<long long>( "-2300000", &errc );
345 REQUIRE( static_cast<long long>( val ) == -2300000 );
346 REQUIRE( errc == mx::error_t::noerror );
347 }
348
349 SECTION( "positive overflow, w/ error check" )
350 {
351 mx::error_t errc;
352 long long val = stoT<long long>( "9223372036854775808", &errc );
353 REQUIRE( static_cast<long long>( val ) == std::numeric_limits<long long>::max() );
354 REQUIRE( errc == mx::error_t::erange );
355 }
356
357 SECTION( "negative overflow, w/ error check" )
358 {
359 mx::error_t errc;
360 long long val = stoT<long long>( "-9223372036854775809", &errc );
361 REQUIRE( static_cast<long long>( val ) == std::numeric_limits<long long>::lowest() );
362 REQUIRE( errc == mx::error_t::erange );
363 }
364
365 SECTION( "invalid string, w/ error check" )
366 {
367 mx::error_t errc;
368 long long val = stoT<long long>( "-..8", &errc );
369 REQUIRE( static_cast<long long>( val ) == 0 );
370 REQUIRE( errc == mx::error_t::invalidarg );
371 }
372 }
373
374 SECTION( "a string unsigned long long" )
375 {
376 SECTION( "string valid, positive, no error check" )
377 {
378 unsigned long long val = stoT<unsigned long long>( "400000000000" );
379 REQUIRE( static_cast<unsigned long long>( val ) == 400000000000 );
380 }
381
382 SECTION( "string valid, w/ error check" )
383 {
384 mx::error_t errc;
385 unsigned long long val = stoT<unsigned long long>( "16", &errc );
386 REQUIRE( static_cast<unsigned long long>( val ) == 16 );
387 REQUIRE( errc == mx::error_t::noerror );
388 }
389
390 SECTION( "positive overflow, w/ error check" )
391 {
392 mx::error_t errc;
393 unsigned long long val = stoT<unsigned long long>( "18523372036854775808", &errc );
394 REQUIRE( static_cast<unsigned long long>( val ) == std::numeric_limits<unsigned long long>::max() );
395 REQUIRE( errc == mx::error_t::erange );
396 }
397
398 SECTION( "invalid string, w/ error check" )
399 {
400 mx::error_t errc;
401 unsigned long long val = stoT<unsigned long long>( "++9.2", &errc );
402 REQUIRE( static_cast<unsigned long long>( val ) == 0 );
403 REQUIRE( errc == mx::error_t::invalidarg );
404 }
405 }
406
407 SECTION( "a string bool" )
408 {
409 SECTION( "string valid, true, no error check" )
410 {
411 bool val = stoT<bool>( "true" );
412 REQUIRE( static_cast<bool>( val ) == true );
413 }
414
415 SECTION( "string valid, false, w/ error check" )
416 {
417 mx::error_t errc;
418 bool val = stoT<bool>( "false", &errc );
419 REQUIRE( static_cast<bool>( val ) == false );
420 REQUIRE( errc == mx::error_t::noerror );
421 }
422
423 SECTION( "string valid, t, w/ error check" )
424 {
425 mx::error_t errc;
426 bool val = stoT<bool>( "t", &errc );
427 REQUIRE( static_cast<bool>( val ) == true );
428 REQUIRE( errc == mx::error_t::noerror );
429 }
430
431 SECTION( "string valid, f, w/ error check" )
432 {
433 mx::error_t errc;
434 bool val = stoT<bool>( "false", &errc );
435 REQUIRE( static_cast<bool>( val ) == false );
436 REQUIRE( errc == mx::error_t::noerror );
437 }
438
439 SECTION( "string valid, 1, w/ error check" )
440 {
441 mx::error_t errc;
442 bool val = stoT<bool>( "1", &errc );
443 REQUIRE( static_cast<bool>( val ) == true );
444 REQUIRE( errc == mx::error_t::noerror );
445 }
446
447 SECTION( "string valid, 0, w/ error check" )
448 {
449 mx::error_t errc;
450 bool val = stoT<bool>( "0", &errc );
451 REQUIRE( static_cast<bool>( val ) == false );
452 REQUIRE( errc == mx::error_t::noerror );
453 }
454
455 SECTION( "string valid, number > 1, w/ error check" )
456 {
457 mx::error_t errc;
458 bool val = stoT<bool>( "237", &errc );
459 REQUIRE( static_cast<bool>( val ) == true );
460 REQUIRE( errc == mx::error_t::noerror );
461 }
462
463 SECTION( "string valid, -0, w/ error check" )
464 {
465 mx::error_t errc;
466 bool val = stoT<bool>( "-0.2", &errc );
467 REQUIRE( static_cast<bool>( val ) == false );
468 REQUIRE( errc == mx::error_t::noerror );
469 }
470
471 SECTION( "invalid string, w/ error check" )
472 {
473 mx::error_t errc;
474 bool val = stoT<bool>( "Xtrue", &errc );
475 REQUIRE( static_cast<bool>( val ) == 0 );
476 REQUIRE( errc == mx::error_t::invalidarg );
477 }
478
479 SECTION( "string valid w/ leading spaces, t, w/ error check" )
480 {
481 mx::error_t errc;
482 bool val = stoT<bool>( " t", &errc );
483 REQUIRE( static_cast<bool>( val ) == true );
484 REQUIRE( errc == mx::error_t::noerror );
485 }
486 }
487
488 SECTION( "a string float" )
489 {
490 SECTION( "string valid, positive, no error check" )
491 {
492 float val = stoT<float>( "2.567" );
493 REQUIRE_THAT( val, WithinRel( static_cast<float>( 2.567 ), std::numeric_limits<float>::epsilon() ) );
494 }
495
496 SECTION( "string valid, negative, w/ error check" )
497 {
498 mx::error_t errc;
499 float val = stoT<float>( "-2300000.897", &errc );
500 REQUIRE_THAT( val, WithinRel( static_cast<float>( -2300000.897 ), std::numeric_limits<float>::epsilon() ) );
501 REQUIRE( errc == mx::error_t::noerror );
502 }
503
504 SECTION( "positive overflow, w/ error check" )
505 {
506 mx::error_t errc;
507 float val = stoT<float>( "1e55", &errc );
508 // inf comparison won't work
509 REQUIRE( errc == mx::error_t::erange );
510 }
511
512 SECTION( "negative overflow, w/ error check" )
513 {
514 mx::error_t errc;
515 float val = stoT<float>( "-1e55", &errc );
516 // inf comparison won't work
517 REQUIRE( errc == mx::error_t::erange );
518 }
519
520 SECTION( "invalid string, w/ error check" )
521 {
522 mx::error_t errc;
523 float val = stoT<float>( "r5", &errc );
524 REQUIRE( static_cast<float>( val ) == 0 );
525 REQUIRE( errc == mx::error_t::invalidarg );
526 }
527
528 SECTION( "string valid w/ leading spaces, negative, w/ error check" )
529 {
530 mx::error_t errc;
531 float val = stoT<float>( " -2300000.897", &errc );
532 REQUIRE_THAT( val, WithinRel( static_cast<float>( -2300000.897 ), std::numeric_limits<float>::epsilon() ) );
533 REQUIRE( errc == mx::error_t::noerror );
534 }
535 }
536
537 SECTION( "a string double" )
538 {
539 SECTION( "string valid, positive, no error check" )
540 {
541 double val = stoT<double>( "22.2567" );
542 REQUIRE_THAT( val, WithinRel( static_cast<double>( 22.2567 ), std::numeric_limits<double>::epsilon() ) );
543 }
544
545 SECTION( "string valid, negative, w/ error check" )
546 {
547 mx::error_t errc;
548 double val = stoT<double>( "-2300000.897987", &errc );
549 REQUIRE_THAT( val,
550 WithinRel( static_cast<double>( -2300000.897987 ), std::numeric_limits<double>::epsilon() ) );
551 REQUIRE( errc == mx::error_t::noerror );
552 }
553
554 SECTION( "positive overflow, w/ error check" )
555 {
556 mx::error_t errc;
557 double val = stoT<double>( "1e400", &errc );
558 // inf comparison won't work
559 REQUIRE( errc == mx::error_t::erange );
560 }
561
562 SECTION( "negative overflow, w/ error check" )
563 {
564 mx::error_t errc;
565 double val = stoT<double>( "-1e400", &errc );
566 // inf comparison won't work
567 REQUIRE( errc == mx::error_t::erange );
568 }
569
570 SECTION( "invalid string, w/ error check" )
571 {
572 mx::error_t errc;
573 double val = stoT<double>( "+d", &errc );
574 REQUIRE( static_cast<double>( val ) == 0 );
575 REQUIRE( errc == mx::error_t::invalidarg );
576 }
577 }
578
579 SECTION( "a string long double" )
580 {
581 // These long double values don't seem quite right, should be able to use epsilon.
582 // new catch2 might work better
583 SECTION( "string valid, positive, no error check" )
584 {
585 long double val = stoT<long double>( "22.2567" );
586 REQUIRE_THAT( static_cast<double>( val ), Catch::Matchers::WithinRel( 22.2567, 1e-9 ) );
587 }
588
589 SECTION( "string valid, negative, w/ error check" )
590 {
591 mx::error_t errc;
592 long double val = stoT<long double>( "-2300000.897987", &errc );
593 REQUIRE_THAT( static_cast<double>( val ), Catch::Matchers::WithinRel( -2300000.897987, 1e-9 ) );
594 REQUIRE( errc == mx::error_t::noerror );
595 }
596
597 SECTION( "positive overflow, w/ error check" )
598 {
599 mx::error_t errc;
600 long double val = stoT<long double>( "1e10000", &errc );
601 // inf comparison won't work
602 REQUIRE( errc == mx::error_t::erange );
603 }
604
605 SECTION( "negative overflow, w/ error check" )
606 {
607 mx::error_t errc;
608 long double val = stoT<long double>( "-1e10000", &errc );
609 // inf comparison won't work
610 REQUIRE( errc == mx::error_t::erange );
611 }
612
613 SECTION( "invalid string, w/ error check" )
614 {
615 mx::error_t errc;
616 long double val = stoT<long double>( "+d", &errc );
617 REQUIRE( static_cast<long double>( val ) == 0 );
618 REQUIRE( errc == mx::error_t::invalidarg );
619 }
620 }
621}
622
623} // namespace stringUtilsTest
624} // namespace ioutilsTest
625} // namespace unitTest
error_t
The mxlib error codes.
Definition error_t.hpp:26
@ noerror
No error has occurred.
@ erange
Numerical result out of range (ERANGE)
@ invalidarg
An argument was invalid.
TEST_CASE("Converting strings to numbers", "[ioutils::stringUtils]")
Converting strings to numbers.
The mxlib c++ namespace.
Definition mxlib.hpp:37