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

Last change on this file since cd1e3fc0 was d7f7a4a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Replace some license headers with SPDX identifier

Headers are replaced using tools/transorm-copyright.sh only
when it can be matched verbatim with the license header used
throughout most of the codebase.

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