source: mainline/uspace/lib/c/test/strtol.c

Last change on this file was 1c9bf292, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Reunite uspace string-to-int conversion functions

  • Property mode set to 100644
File size: 14.4 KB
Line 
1/*
2 * Copyright (c) 2018 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/**
33 * @file
34 * @brief Test string to int conversion functions
35 */
36
37#include <pcut/pcut.h>
38#include <stdlib.h>
39#include <str.h>
40#include <limits.h>
41
42PCUT_INIT;
43
44PCUT_TEST_SUITE(strtol);
45
46/** atoi function */
47PCUT_TEST(atoi)
48{
49 int i;
50
51 i = atoi(" \t42");
52 PCUT_ASSERT_TRUE(i == 42);
53}
54
55/** atol function */
56PCUT_TEST(atol)
57{
58 long li;
59
60 li = atol(" \t42");
61 PCUT_ASSERT_TRUE(li == 42);
62}
63
64/** atoll function */
65PCUT_TEST(atoll)
66{
67 long long lli;
68
69 lli = atoll(" \t42");
70 PCUT_ASSERT_TRUE(lli == 42);
71}
72
73/** strtol function */
74PCUT_TEST(strtol)
75{
76 long li;
77 char *ep;
78
79 li = strtol(" \t42x", &ep, 10);
80 PCUT_ASSERT_TRUE(li == 42);
81 PCUT_ASSERT_TRUE(*ep == 'x');
82}
83
84/** strtol function with auto-detected base 10 */
85PCUT_TEST(strtol_dec_auto)
86{
87 long li;
88 char *ep;
89
90 li = strtol(" \t42x", &ep, 0);
91 PCUT_ASSERT_TRUE(li == 42);
92 PCUT_ASSERT_TRUE(*ep == 'x');
93}
94
95/** strtol function with octal number */
96PCUT_TEST(strtol_oct)
97{
98 long li;
99 char *ep;
100
101 li = strtol(" \t052x", &ep, 8);
102 PCUT_ASSERT_TRUE(li == 052);
103 PCUT_ASSERT_TRUE(*ep == 'x');
104}
105
106/** strtol function with octal number with prefix */
107#include <stdio.h>
108PCUT_TEST(strtol_oct_prefix)
109{
110 long li;
111 char *ep;
112
113 li = strtol(" \t052x", &ep, 0);
114 printf("li=%ld (0%lo)\n", li, li);
115 PCUT_ASSERT_TRUE(li == 052);
116 PCUT_ASSERT_TRUE(*ep == 'x');
117}
118
119/** strtol function with hex number */
120PCUT_TEST(strtol_hex)
121{
122 long li;
123 char *ep;
124
125 li = strtol(" \t2ax", &ep, 16);
126 PCUT_ASSERT_TRUE(li == 0x2a);
127 PCUT_ASSERT_TRUE(*ep == 'x');
128}
129
130/** strtol function with hex number with hex prefix */
131PCUT_TEST(strtol_hex_prefixed)
132{
133 long li;
134 char *ep;
135
136 li = strtol(" \t0x2ax", &ep, 0);
137 PCUT_ASSERT_TRUE(li == 0x2a);
138 PCUT_ASSERT_TRUE(*ep == 'x');
139}
140
141/** strtol function with base 16 and number with 0x prefix */
142PCUT_TEST(strtol_base16_prefix)
143{
144 long li;
145 char *ep;
146
147 li = strtol(" \t0x1y", &ep, 16);
148 printf("li=%ld\n", li);
149 PCUT_ASSERT_TRUE(li == 1);
150 PCUT_ASSERT_TRUE(*ep == 'y');
151}
152
153/** strtol function with base 36 number */
154PCUT_TEST(strtol_base36)
155{
156 long li;
157 char *ep;
158
159 li = strtol(" \tz1.", &ep, 36);
160 PCUT_ASSERT_TRUE(li == 35 * 36 + 1);
161 PCUT_ASSERT_TRUE(*ep == '.');
162}
163
164PCUT_TEST(str_uint_hex)
165{
166 int base;
167 bool strict;
168 const char *endp;
169 uint32_t result;
170 errno_t rc;
171 const char *input;
172
173 /*
174 * str_* conversion function do not admit a prefix when base is
175 * specified.
176 */
177
178 rc = str_uint32_t(input = "0x10", &endp, base = 0, strict = false, &result);
179 PCUT_ASSERT_INT_EQUALS(EOK, rc);
180 PCUT_ASSERT_INT_EQUALS(0x10, result);
181 PCUT_ASSERT_PTR_EQUALS(input + 4, endp);
182
183 rc = str_uint32_t(input = "0x10", &endp, base = 16, strict = false, &result);
184 PCUT_ASSERT_INT_EQUALS(EOK, rc);
185 PCUT_ASSERT_INT_EQUALS(0, result);
186 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
187
188 rc = str_uint32_t(input = " \t0x10", &endp, base = 0, strict = false, &result);
189 PCUT_ASSERT_INT_EQUALS(EOK, rc);
190 PCUT_ASSERT_INT_EQUALS(0x10, result);
191 PCUT_ASSERT_PTR_EQUALS(input + 7, endp);
192
193 rc = str_uint32_t(input = " \t0x10", &endp, base = 16, strict = false, &result);
194 PCUT_ASSERT_INT_EQUALS(EOK, rc);
195 PCUT_ASSERT_INT_EQUALS(0, result);
196 PCUT_ASSERT_PTR_EQUALS(input + 4, endp);
197}
198
199PCUT_TEST(str_uint_overflow)
200{
201 int base;
202 bool strict;
203 uint64_t result;
204 errno_t rc;
205 const char *input;
206
207 /*
208 * Naive overflow check will not detect this overflow,
209 * since the intermediate result is equal to the previous step.
210 */
211
212 rc = str_uint64_t(input = "0xffffffffffffffffffffffffffffffff", NULL, base = 0, strict = false, &result);
213#if 0
214 /* Buggy result. */
215 PCUT_ASSERT_INT_EQUALS(EOK, rc);
216 PCUT_ASSERT_UINT_EQUALS(0xffffffffffffffff, result);
217#else
218 /* Correct result. */
219 PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc);
220#endif
221
222 /* 3^40 */
223
224 rc = str_uint64_t(input = "1" "0000000000" "0000000000" "0000000000" "0000000000", NULL, base = 3, strict = false, &result);
225 PCUT_ASSERT_INT_EQUALS(EOK, rc);
226 PCUT_ASSERT_UINT_EQUALS(0xa8b8b452291fe821, result);
227
228 /*
229 * Naive overflow check will not detect this overflow,
230 * since the intermediate result is greater than the previous step,
231 * despite overflowing 64 bits.
232 *
233 * The input is 3^41 which is greater than 2^64,
234 * but (3^41 mod 2^64) is still greater than 3^40, so overflow is not
235 * detected by a naive magnitude check.
236 */
237
238 rc = str_uint64_t(input = "10" "0000000000" "0000000000" "0000000000" "0000000000", NULL, base = 3, strict = false, &result);
239#if 0
240 /* Buggy result. */
241 PCUT_ASSERT_INT_EQUALS(EOK, rc);
242 /* Correct value is 0x1fa2a1cf67b5fb863 */
243 PCUT_ASSERT_UINT_EQUALS(0xfa2a1cf67b5fb863, result);
244#else
245 /* Correct result. */
246 PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc);
247#endif
248}
249
250PCUT_TEST(strtoul_negative_wraparound)
251{
252 long output;
253 char *endp;
254 char *endp_unchanged = (char *) "endp_unchanged unique pointer";
255 int errno_unchanged = -1;
256 const char *input;
257 int base;
258
259 /*
260 * N2176 7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions
261 *
262 * "If the subject sequence begins with a minus sign, the value
263 * resulting from the conversion is negated (in the return type)."
264 */
265
266 endp = endp_unchanged;
267 errno = errno_unchanged;
268 output = strtoul(input = "-10", &endp, base = 0);
269 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
270 PCUT_ASSERT_PTR_EQUALS(input + 3, endp);
271 PCUT_ASSERT_UINT_EQUALS(-(10ul), output);
272}
273
274PCUT_TEST(strtol_fringe)
275{
276 long output;
277 char *endp;
278 char *endp_unchanged = (char *) "endp_unchanged unique pointer";
279 int errno_unchanged = -1;
280 const char *input;
281 int base;
282
283 /* Variants of plain zero with various bases. */
284 endp = endp_unchanged;
285 errno = errno_unchanged;
286 output = strtol(input = "0", &endp, base = 0);
287 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
288 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
289 PCUT_ASSERT_INT_EQUALS(0, output);
290
291 endp = endp_unchanged;
292 errno = errno_unchanged;
293 output = strtol(input = "0", &endp, base = -10);
294 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
295 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
296 PCUT_ASSERT_INT_EQUALS(0, output);
297
298 endp = endp_unchanged;
299 errno = errno_unchanged;
300 output = strtol(input = "0", &endp, base = 1);
301 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
302 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
303 PCUT_ASSERT_INT_EQUALS(0, output);
304
305 for (base = 2; base <= 36; base++) {
306 endp = endp_unchanged;
307 errno = errno_unchanged;
308 output = strtol(input = "0", &endp, base);
309 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
310 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
311 PCUT_ASSERT_INT_EQUALS(0, output);
312
313 endp = endp_unchanged;
314 errno = errno_unchanged;
315 output = strtol(input = "1", &endp, base);
316 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
317 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
318 PCUT_ASSERT_INT_EQUALS(1, output);
319
320 endp = endp_unchanged;
321 errno = errno_unchanged;
322 output = strtol(input = "10", &endp, base);
323 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
324 PCUT_ASSERT_PTR_EQUALS(input + 2, endp);
325 PCUT_ASSERT_INT_EQUALS(base, output);
326
327 endp = endp_unchanged;
328 errno = errno_unchanged;
329 output = strtol(input = "100", &endp, base);
330 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
331 PCUT_ASSERT_PTR_EQUALS(input + 3, endp);
332 PCUT_ASSERT_INT_EQUALS(base * base, output);
333
334 endp = endp_unchanged;
335 errno = errno_unchanged;
336 output = strtol(input = "1000", &endp, base);
337 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
338 PCUT_ASSERT_PTR_EQUALS(input + 4, endp);
339 PCUT_ASSERT_INT_EQUALS(base * base * base, output);
340 }
341
342 endp = endp_unchanged;
343 errno = errno_unchanged;
344 output = strtol(input = "0", &endp, base = 8);
345 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
346 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
347 PCUT_ASSERT_INT_EQUALS(0, output);
348
349 endp = endp_unchanged;
350 errno = errno_unchanged;
351 output = strtol(input = "0", &endp, base = 10);
352 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
353 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
354 PCUT_ASSERT_INT_EQUALS(0, output);
355
356 endp = endp_unchanged;
357 errno = errno_unchanged;
358 output = strtol(input = "0", &endp, base = 16);
359 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
360 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
361 PCUT_ASSERT_INT_EQUALS(0, output);
362
363 endp = endp_unchanged;
364 errno = errno_unchanged;
365 output = strtol(input = "0", &endp, base = 36);
366 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
367 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
368 PCUT_ASSERT_INT_EQUALS(0, output);
369
370 endp = endp_unchanged;
371 errno = errno_unchanged;
372 output = strtol(input = "0", &endp, base = 37);
373 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
374 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
375 PCUT_ASSERT_INT_EQUALS(0, output);
376
377 endp = endp_unchanged;
378 errno = errno_unchanged;
379 output = strtol(input = "0", &endp, base = 37);
380 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
381 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
382 PCUT_ASSERT_INT_EQUALS(0, output);
383
384 /* No valid number */
385 endp = endp_unchanged;
386 errno = errno_unchanged;
387 output = strtol(input = "", &endp, base = 0);
388 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
389 PCUT_ASSERT_PTR_EQUALS(input, endp);
390 PCUT_ASSERT_INT_EQUALS(0, output);
391
392 endp = endp_unchanged;
393 errno = errno_unchanged;
394 output = strtol(input = " ", &endp, base = 0);
395 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
396 PCUT_ASSERT_PTR_EQUALS(input, endp);
397 PCUT_ASSERT_INT_EQUALS(0, output);
398
399 endp = endp_unchanged;
400 errno = errno_unchanged;
401 output = strtol(input = " ", &endp, base = 10);
402 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
403 PCUT_ASSERT_PTR_EQUALS(input, endp);
404 PCUT_ASSERT_INT_EQUALS(0, output);
405
406 endp = endp_unchanged;
407 errno = errno_unchanged;
408 output = strtol(input = " x", &endp, base = 0);
409 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
410 PCUT_ASSERT_PTR_EQUALS(input, endp);
411 PCUT_ASSERT_INT_EQUALS(0, output);
412
413 endp = endp_unchanged;
414 errno = errno_unchanged;
415 output = strtol(input = " x0", &endp, base = 0);
416 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
417 PCUT_ASSERT_PTR_EQUALS(input, endp);
418 PCUT_ASSERT_INT_EQUALS(0, output);
419
420 endp = endp_unchanged;
421 errno = errno_unchanged;
422 output = strtol(input = " 0x", &endp, base = 0);
423 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
424 PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
425 PCUT_ASSERT_INT_EQUALS(0, output);
426
427 endp = endp_unchanged;
428 errno = errno_unchanged;
429 output = strtol(input = " 0xg", &endp, base = 0);
430 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
431 PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
432 PCUT_ASSERT_INT_EQUALS(0, output);
433
434 endp = endp_unchanged;
435 errno = errno_unchanged;
436 output = strtol(input = " 0x1", &endp, base = 0);
437 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
438 PCUT_ASSERT_PTR_EQUALS(input + 7, endp);
439 PCUT_ASSERT_INT_EQUALS(1, output);
440
441 endp = endp_unchanged;
442 errno = errno_unchanged;
443 output = strtol(input = " 0x", &endp, base = 16);
444 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
445 PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
446 PCUT_ASSERT_INT_EQUALS(0, output);
447
448 endp = endp_unchanged;
449 errno = errno_unchanged;
450 output = strtol(input = " 0xg", &endp, base = 16);
451 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
452 PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
453 PCUT_ASSERT_INT_EQUALS(0, output);
454
455 endp = endp_unchanged;
456 errno = errno_unchanged;
457 output = strtol(input = " g", &endp, base = 16);
458 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
459 PCUT_ASSERT_PTR_EQUALS(input, endp);
460 PCUT_ASSERT_INT_EQUALS(0, output);
461
462 endp = endp_unchanged;
463 errno = errno_unchanged;
464 output = strtol(input = " 0x1", &endp, base = 16);
465 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
466 PCUT_ASSERT_PTR_EQUALS(input + 7, endp);
467 PCUT_ASSERT_INT_EQUALS(1, output);
468
469 endp = endp_unchanged;
470 errno = errno_unchanged;
471 output = strtol(input = " +", &endp, base = 0);
472 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
473 PCUT_ASSERT_PTR_EQUALS(input, endp);
474 PCUT_ASSERT_INT_EQUALS(0, output);
475
476 endp = endp_unchanged;
477 errno = errno_unchanged;
478 output = strtol(input = " -", &endp, base = 0);
479 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
480 PCUT_ASSERT_PTR_EQUALS(input, endp);
481 PCUT_ASSERT_INT_EQUALS(0, output);
482
483 endp = endp_unchanged;
484 errno = errno_unchanged;
485 output = strtol(input = " +", &endp, base = 10);
486 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
487 PCUT_ASSERT_PTR_EQUALS(input, endp);
488 PCUT_ASSERT_INT_EQUALS(0, output);
489
490 endp = endp_unchanged;
491 errno = errno_unchanged;
492 output = strtol(input = " -", &endp, base = 10);
493 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
494 PCUT_ASSERT_PTR_EQUALS(input, endp);
495 PCUT_ASSERT_INT_EQUALS(0, output);
496
497 endp = endp_unchanged;
498 errno = errno_unchanged;
499 output = strtol(input = "+", &endp, base = 0);
500 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
501 PCUT_ASSERT_PTR_EQUALS(input, endp);
502 PCUT_ASSERT_INT_EQUALS(0, output);
503
504 endp = endp_unchanged;
505 errno = errno_unchanged;
506 output = strtol(input = "-", &endp, base = 0);
507 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
508 PCUT_ASSERT_PTR_EQUALS(input, endp);
509 PCUT_ASSERT_INT_EQUALS(0, output);
510
511 endp = endp_unchanged;
512 errno = errno_unchanged;
513 output = strtol(input = "+", &endp, base = 10);
514 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
515 PCUT_ASSERT_PTR_EQUALS(input, endp);
516 PCUT_ASSERT_INT_EQUALS(0, output);
517
518 endp = endp_unchanged;
519 errno = errno_unchanged;
520 output = strtol(input = "-", &endp, base = 10);
521 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
522 PCUT_ASSERT_PTR_EQUALS(input, endp);
523 PCUT_ASSERT_INT_EQUALS(0, output);
524}
525
526PCUT_EXPORT(strtol);
Note: See TracBrowser for help on using the repository browser.