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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a4e78743 was a4e78743, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Move string-to-int conversion tests to a separate file, and add a few

Some of the newly added tests detect bugs in current implementation.
Fixes and more tests are WIP.

  • Property mode set to 100644
File size: 11.5 KB
RevLine 
[a4e78743]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
41PCUT_INIT;
42
43PCUT_TEST_SUITE(strtol);
44
45/** atoi function */
46PCUT_TEST(atoi)
47{
48 int i;
49
50 i = atoi(" \t42");
51 PCUT_ASSERT_TRUE(i == 42);
52}
53
54/** atol function */
55PCUT_TEST(atol)
56{
57 long li;
58
59 li = atol(" \t42");
60 PCUT_ASSERT_TRUE(li == 42);
61}
62
63/** atoll function */
64PCUT_TEST(atoll)
65{
66 long long lli;
67
68 lli = atoll(" \t42");
69 PCUT_ASSERT_TRUE(lli == 42);
70}
71
72/** strtol function */
73PCUT_TEST(strtol)
74{
75 long li;
76 char *ep;
77
78 li = strtol(" \t42x", &ep, 10);
79 PCUT_ASSERT_TRUE(li == 42);
80 PCUT_ASSERT_TRUE(*ep == 'x');
81}
82
83/** strtol function with auto-detected base 10 */
84PCUT_TEST(strtol_dec_auto)
85{
86 long li;
87 char *ep;
88
89 li = strtol(" \t42x", &ep, 0);
90 PCUT_ASSERT_TRUE(li == 42);
91 PCUT_ASSERT_TRUE(*ep == 'x');
92}
93
94/** strtol function with octal number */
95PCUT_TEST(strtol_oct)
96{
97 long li;
98 char *ep;
99
100 li = strtol(" \t052x", &ep, 8);
101 PCUT_ASSERT_TRUE(li == 052);
102 PCUT_ASSERT_TRUE(*ep == 'x');
103}
104
105/** strtol function with octal number with prefix */
106#include <stdio.h>
107PCUT_TEST(strtol_oct_prefix)
108{
109 long li;
110 char *ep;
111
112 li = strtol(" \t052x", &ep, 0);
113 printf("li=%ld (0%lo)\n", li, li);
114 PCUT_ASSERT_TRUE(li == 052);
115 PCUT_ASSERT_TRUE(*ep == 'x');
116}
117
118/** strtol function with hex number */
119PCUT_TEST(strtol_hex)
120{
121 long li;
122 char *ep;
123
124 li = strtol(" \t2ax", &ep, 16);
125 PCUT_ASSERT_TRUE(li == 0x2a);
126 PCUT_ASSERT_TRUE(*ep == 'x');
127}
128
129/** strtol function with hex number with hex prefix */
130PCUT_TEST(strtol_hex_prefixed)
131{
132 long li;
133 char *ep;
134
135 li = strtol(" \t0x2ax", &ep, 0);
136 PCUT_ASSERT_TRUE(li == 0x2a);
137 PCUT_ASSERT_TRUE(*ep == 'x');
138}
139
140/** strtol function with base 16 and number with 0x prefix */
141PCUT_TEST(strtol_base16_prefix)
142{
143 long li;
144 char *ep;
145
146 li = strtol(" \t0x1y", &ep, 16);
147 printf("li=%ld\n", li);
148 PCUT_ASSERT_TRUE(li == 1);
149 PCUT_ASSERT_TRUE(*ep == 'y');
150}
151
152/** strtol function with base 36 number */
153PCUT_TEST(strtol_base36)
154{
155 long li;
156 char *ep;
157
158 li = strtol(" \tz1.", &ep, 36);
159 PCUT_ASSERT_TRUE(li == 35 * 36 + 1);
160 PCUT_ASSERT_TRUE(*ep == '.');
161}
162
163PCUT_TEST(str_uint_hex)
164{
165 int base;
166 bool strict;
167 const char *endp;
168 uint32_t result;
169 errno_t rc;
170 const char *input;
171
172 /*
173 * str_* conversion function do not admit a prefix when base is
174 * specified.
175 */
176
177 rc = str_uint32_t(input = "0x10", &endp, base = 0, strict = false, &result);
178 PCUT_ASSERT_INT_EQUALS(EOK, rc);
179 PCUT_ASSERT_INT_EQUALS(0x10, result);
180 PCUT_ASSERT_PTR_EQUALS(input + 4, endp);
181
182 rc = str_uint32_t(input = "0x10", &endp, base = 16, strict = false, &result);
183 PCUT_ASSERT_INT_EQUALS(EOK, rc);
184 PCUT_ASSERT_INT_EQUALS(0, result);
185 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
186
187 rc = str_uint32_t(input = " \t0x10", &endp, base = 0, strict = false, &result);
188 PCUT_ASSERT_INT_EQUALS(EOK, rc);
189 PCUT_ASSERT_INT_EQUALS(0x10, result);
190 PCUT_ASSERT_PTR_EQUALS(input + 7, endp);
191
192 rc = str_uint32_t(input = " \t0x10", &endp, base = 16, strict = false, &result);
193 PCUT_ASSERT_INT_EQUALS(EOK, rc);
194 PCUT_ASSERT_INT_EQUALS(0, result);
195 PCUT_ASSERT_PTR_EQUALS(input + 4, endp);
196}
197
198PCUT_TEST(str_uint_overflow)
199{
200 int base;
201 bool strict;
202 uint64_t result;
203 errno_t rc;
204 const char *input;
205
206 /*
207 * Naive overflow check will not detect this overflow,
208 * since the intermediate result is equal to the previous step.
209 */
210
211 rc = str_uint64_t(input = "0xffffffffffffffffffffffffffffffff", NULL, base = 0, strict = false, &result);
212#if 0
213 /* Buggy result. */
214 PCUT_ASSERT_INT_EQUALS(EOK, rc);
215 PCUT_ASSERT_UINT_EQUALS(0xffffffffffffffff, result);
216#else
217 /* Correct result. */
218 PCUT_ASSERT_INT_EQUALS(EOVERFLOW, rc);
219 PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);
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 PCUT_ASSERT_UINT_EQUALS(UINT64_MAX, result);
248#endif
249}
250
251PCUT_TEST(strtol_fringe)
252{
253 long output;
254 char *endp;
255 char *endp_unchanged = (char *) "endp_unchanged unique pointer";
256 int errno_unchanged = -1;
257 const char *input;
258 int base;
259
260 /* Variants of plain zero with various bases. */
261 endp = endp_unchanged;
262 errno = errno_unchanged;
263 output = strtol(input = "0", &endp, base = 0);
264 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
265 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
266 PCUT_ASSERT_INT_EQUALS(0, output);
267
268 endp = endp_unchanged;
269 errno = errno_unchanged;
270 output = strtol(input = "0", &endp, base = -10);
271 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
272 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
273 PCUT_ASSERT_INT_EQUALS(0, output);
274
275 endp = endp_unchanged;
276 errno = errno_unchanged;
277 output = strtol(input = "0", &endp, base = 1);
278 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
279 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
280 PCUT_ASSERT_INT_EQUALS(0, output);
281
282 for (base = 2; base <= 36; base++) {
283 endp = endp_unchanged;
284 errno = errno_unchanged;
285 output = strtol(input = "0", &endp, base);
286 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
287 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
288 PCUT_ASSERT_INT_EQUALS(0, output);
289
290 endp = endp_unchanged;
291 errno = errno_unchanged;
292 output = strtol(input = "1", &endp, base);
293 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
294 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
295 PCUT_ASSERT_INT_EQUALS(1, output);
296
297 endp = endp_unchanged;
298 errno = errno_unchanged;
299 output = strtol(input = "10", &endp, base);
300 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
301 PCUT_ASSERT_PTR_EQUALS(input + 2, endp);
302 PCUT_ASSERT_INT_EQUALS(base, output);
303
304 endp = endp_unchanged;
305 errno = errno_unchanged;
306 output = strtol(input = "100", &endp, base);
307 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
308 PCUT_ASSERT_PTR_EQUALS(input + 3, endp);
309 PCUT_ASSERT_INT_EQUALS(base * base, output);
310
311 endp = endp_unchanged;
312 errno = errno_unchanged;
313 output = strtol(input = "1000", &endp, base);
314 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
315 PCUT_ASSERT_PTR_EQUALS(input + 4, endp);
316 PCUT_ASSERT_INT_EQUALS(base * base * base, output);
317 }
318
319 endp = endp_unchanged;
320 errno = errno_unchanged;
321 output = strtol(input = "0", &endp, base = 8);
322 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
323 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
324 PCUT_ASSERT_INT_EQUALS(0, output);
325
326 endp = endp_unchanged;
327 errno = errno_unchanged;
328 output = strtol(input = "0", &endp, base = 10);
329 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
330 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
331 PCUT_ASSERT_INT_EQUALS(0, output);
332
333 endp = endp_unchanged;
334 errno = errno_unchanged;
335 output = strtol(input = "0", &endp, base = 16);
336 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
337 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
338 PCUT_ASSERT_INT_EQUALS(0, output);
339
340 endp = endp_unchanged;
341 errno = errno_unchanged;
342 output = strtol(input = "0", &endp, base = 36);
343 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
344 PCUT_ASSERT_PTR_EQUALS(input + 1, endp);
345 PCUT_ASSERT_INT_EQUALS(0, output);
346
347 endp = endp_unchanged;
348 errno = errno_unchanged;
349 output = strtol(input = "0", &endp, base = 37);
350 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
351 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
352 PCUT_ASSERT_INT_EQUALS(0, output);
353
354 endp = endp_unchanged;
355 errno = errno_unchanged;
356 output = strtol(input = "0", &endp, base = 37);
357 PCUT_ASSERT_INT_EQUALS(EINVAL, errno);
358 PCUT_ASSERT_PTR_EQUALS(endp_unchanged, endp);
359 PCUT_ASSERT_INT_EQUALS(0, output);
360
361 /* No valid number */
362 endp = endp_unchanged;
363 errno = errno_unchanged;
364 output = strtol(input = "", &endp, base = 0);
365 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
366 PCUT_ASSERT_PTR_EQUALS(input, endp);
367 PCUT_ASSERT_INT_EQUALS(0, output);
368
369 endp = endp_unchanged;
370 errno = errno_unchanged;
371 output = strtol(input = " ", &endp, base = 0);
372 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
373 PCUT_ASSERT_PTR_EQUALS(input, endp);
374 PCUT_ASSERT_INT_EQUALS(0, output);
375
376 endp = endp_unchanged;
377 errno = errno_unchanged;
378 output = strtol(input = " ", &endp, base = 10);
379 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
380 PCUT_ASSERT_PTR_EQUALS(input, endp);
381 PCUT_ASSERT_INT_EQUALS(0, output);
382
383 endp = endp_unchanged;
384 errno = errno_unchanged;
385 output = strtol(input = " x", &endp, base = 0);
386 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
387 PCUT_ASSERT_PTR_EQUALS(input, endp);
388 PCUT_ASSERT_INT_EQUALS(0, output);
389
390 endp = endp_unchanged;
391 errno = errno_unchanged;
392 output = strtol(input = " x0", &endp, base = 0);
393 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
394 PCUT_ASSERT_PTR_EQUALS(input, endp);
395 PCUT_ASSERT_INT_EQUALS(0, output);
396
397 endp = endp_unchanged;
398 errno = errno_unchanged;
399 output = strtol(input = " 0x", &endp, base = 0);
400 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
401 PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
402 PCUT_ASSERT_INT_EQUALS(0, output);
403
404 endp = endp_unchanged;
405 errno = errno_unchanged;
406 output = strtol(input = " 0x1", &endp, base = 0);
407 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
408 PCUT_ASSERT_PTR_EQUALS(input + 7, endp);
409 PCUT_ASSERT_INT_EQUALS(1, output);
410
411 endp = endp_unchanged;
412 errno = errno_unchanged;
413 output = strtol(input = " 0x", &endp, base = 16);
414 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
415 PCUT_ASSERT_PTR_EQUALS(input + 5, endp);
416 PCUT_ASSERT_INT_EQUALS(0, output);
417
418 endp = endp_unchanged;
419 errno = errno_unchanged;
420 output = strtol(input = " 0x1", &endp, base = 16);
421 PCUT_ASSERT_INT_EQUALS(errno_unchanged, errno);
422 PCUT_ASSERT_PTR_EQUALS(input + 7, endp);
423 PCUT_ASSERT_INT_EQUALS(1, output);
424}
425
426PCUT_EXPORT(strtol);
Note: See TracBrowser for help on using the repository browser.