source: mainline/uspace/lib/c/test/stdio/scanf.c@ d1582b50

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d1582b50 was d1582b50, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Fix spacing in single-line comments using latest ccheck

This found incorrectly formatted section comments (with blocks of
asterisks or dashes). I strongly believe against using section comments
but I am not simply removing them since that would probably be
controversial.

  • Property mode set to 100644
File size: 26.6 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 formatted input (scanf family)
35 */
36
37#include <mem.h>
38#include <pcut/pcut.h>
39#include <stddef.h>
40#include <stdint.h>
41#include <stdio.h>
42#include <stdlib.h>
43
44#pragma GCC diagnostic ignored "-Wformat-zero-length"
45#pragma GCC diagnostic ignored "-Wformat"
46#pragma GCC diagnostic ignored "-Wformat-extra-args"
47
48PCUT_INIT;
49
50PCUT_TEST_SUITE(scanf);
51
52enum {
53 chars_size = 10
54};
55
56/** Empty format string */
57PCUT_TEST(empty_fmt)
58{
59 int rc;
60
61 rc = sscanf("42", "");
62 PCUT_ASSERT_INT_EQUALS(0, rc);
63}
64
65/** Decimal integer */
66PCUT_TEST(dec_int)
67{
68 int rc;
69 int i;
70
71 rc = sscanf("42", "%d", &i);
72 PCUT_ASSERT_INT_EQUALS(1, rc);
73 PCUT_ASSERT_TRUE(i == 42);
74}
75
76/** Two integers */
77PCUT_TEST(int_int)
78{
79 int rc;
80 int i, j;
81
82 rc = sscanf("42 43", "%d%d", &i, &j);
83 PCUT_ASSERT_INT_EQUALS(2, rc);
84 PCUT_ASSERT_TRUE(i == 42);
85 PCUT_ASSERT_TRUE(j == 43);
86}
87
88/** Decimal signed char */
89PCUT_TEST(dec_sign_char)
90{
91 int rc;
92 signed char sc;
93
94 rc = sscanf("42", "%hhd", &sc);
95 PCUT_ASSERT_INT_EQUALS(1, rc);
96 PCUT_ASSERT_TRUE(sc == 42);
97}
98
99/** Decimal short */
100PCUT_TEST(dec_short)
101{
102 int rc;
103 short si;
104
105 rc = sscanf("42", "%hd", &si);
106 PCUT_ASSERT_INT_EQUALS(1, rc);
107 PCUT_ASSERT_TRUE(si == 42);
108}
109
110/** Decimal long */
111PCUT_TEST(dec_long)
112{
113 int rc;
114 long li;
115
116 rc = sscanf("42", "%ld", &li);
117 PCUT_ASSERT_INT_EQUALS(1, rc);
118 PCUT_ASSERT_TRUE(li == 42);
119}
120
121/** Decimal long long */
122PCUT_TEST(dec_long_long)
123{
124 int rc;
125 long long lli;
126
127 rc = sscanf("42", "%lld", &lli);
128 PCUT_ASSERT_INT_EQUALS(1, rc);
129 PCUT_ASSERT_TRUE(lli == 42);
130}
131
132/** Decimal intmax_t */
133PCUT_TEST(dec_intmax)
134{
135 int rc;
136 intmax_t imax;
137
138 rc = sscanf("42", "%jd", &imax);
139 PCUT_ASSERT_INT_EQUALS(1, rc);
140 PCUT_ASSERT_TRUE(imax == 42);
141}
142
143/** Decimal size_t-sized */
144PCUT_TEST(dec_size_t_size)
145{
146 int rc;
147 size_t szi;
148
149 rc = sscanf("42", "%zd", &szi);
150 PCUT_ASSERT_INT_EQUALS(1, rc);
151 PCUT_ASSERT_TRUE(szi == 42);
152}
153
154/** Decimal ptrdiff_t-sized */
155PCUT_TEST(dec_ptrdiff_t_size)
156{
157 int rc;
158 ptrdiff_t pdi;
159
160 rc = sscanf("42", "%td", &pdi);
161 PCUT_ASSERT_INT_EQUALS(1, rc);
162 PCUT_ASSERT_TRUE(pdi == 42);
163}
164
165/** Decimal integer followed by hexadecimal digit */
166PCUT_TEST(dec_int_hexdigit)
167{
168 int rc;
169 int i;
170
171 rc = sscanf("42a", "%d", &i);
172 PCUT_ASSERT_INT_EQUALS(1, rc);
173 PCUT_ASSERT_TRUE(i == 42);
174}
175
176/** Decimal integer - detect no prefix */
177PCUT_TEST(int_noprefix)
178{
179 int rc;
180 int i;
181
182 rc = sscanf("42", "%i", &i);
183 PCUT_ASSERT_INT_EQUALS(1, rc);
184 PCUT_ASSERT_TRUE(i == 42);
185}
186
187/** Prefixed octal integer followed by decimal digit */
188PCUT_TEST(octal_decimal_digit)
189{
190 int rc;
191 int i;
192
193 rc = sscanf("019", "%i", &i);
194 PCUT_ASSERT_INT_EQUALS(1, rc);
195 PCUT_ASSERT_TRUE(i == 1);
196}
197
198/** Prefixed hexadecimal integer followed by other character */
199PCUT_TEST(hex_other_char)
200{
201 int rc;
202 int i;
203
204 rc = sscanf("0xag", "%i", &i);
205 PCUT_ASSERT_INT_EQUALS(1, rc);
206 PCUT_ASSERT_TRUE(i == 10);
207}
208
209/** Decimal integer with '+' sign */
210PCUT_TEST(positive_dec)
211{
212 int rc;
213 int i;
214
215 rc = sscanf("+42", "%d", &i);
216 PCUT_ASSERT_INT_EQUALS(1, rc);
217 PCUT_ASSERT_TRUE(i == 42);
218}
219
220/** Decimal integer with '-' sign */
221PCUT_TEST(negative_dec)
222{
223 int rc;
224 int i;
225
226 rc = sscanf("-42", "%d", &i);
227 PCUT_ASSERT_INT_EQUALS(1, rc);
228 PCUT_ASSERT_TRUE(i == -42);
229}
230
231/** Hexadecimal integer with prefix and '-' sign */
232PCUT_TEST(negative_hex)
233{
234 int rc;
235 int i;
236
237 rc = sscanf("-0xa", "%i", &i);
238 PCUT_ASSERT_INT_EQUALS(1, rc);
239 PCUT_ASSERT_TRUE(i == -10);
240}
241
242/** Decimal unsigned integer */
243PCUT_TEST(dec_unsigned)
244{
245 int rc;
246 unsigned u;
247
248 rc = sscanf("42", "%u", &u);
249 PCUT_ASSERT_INT_EQUALS(1, rc);
250 PCUT_ASSERT_TRUE(u == 42);
251}
252
253/** Decimal unsigned char */
254PCUT_TEST(dec_unsigned_char)
255{
256 int rc;
257 unsigned char uc;
258
259 rc = sscanf("42", "%hhu", &uc);
260 PCUT_ASSERT_INT_EQUALS(1, rc);
261 PCUT_ASSERT_TRUE(uc == 42);
262}
263
264/** Decimal unsigned short */
265PCUT_TEST(dec_unsigned_short)
266{
267 int rc;
268 unsigned short su;
269
270 rc = sscanf("42", "%hu", &su);
271 PCUT_ASSERT_INT_EQUALS(1, rc);
272 PCUT_ASSERT_TRUE(su == 42);
273}
274
275/** Decimal unsigned long */
276PCUT_TEST(dec_unsigned_long)
277{
278 int rc;
279 unsigned long lu;
280
281 rc = sscanf("42", "%lu", &lu);
282 PCUT_ASSERT_INT_EQUALS(1, rc);
283 PCUT_ASSERT_TRUE(lu == 42);
284}
285
286/** Decimal unsigned long long */
287PCUT_TEST(dec_unsigned_long_long)
288{
289 int rc;
290 unsigned long long llu;
291
292 rc = sscanf("42", "%llu", &llu);
293 PCUT_ASSERT_INT_EQUALS(1, rc);
294 PCUT_ASSERT_TRUE(llu == 42);
295}
296
297/** Decimal uintmax_t */
298PCUT_TEST(dec_unitmax)
299{
300 int rc;
301 uintmax_t umax;
302
303 rc = sscanf("42", "%ju", &umax);
304 PCUT_ASSERT_INT_EQUALS(1, rc);
305 PCUT_ASSERT_TRUE(umax == 42);
306}
307
308/** Decimal size_t */
309PCUT_TEST(dec_unsigned_size)
310{
311 int rc;
312 size_t szu;
313
314 rc = sscanf("42", "%zu", &szu);
315 PCUT_ASSERT_INT_EQUALS(1, rc);
316 PCUT_ASSERT_TRUE(szu == 42);
317}
318
319/** Decimal ptrdiff_t-sized unsigned int */
320PCUT_TEST(dec_unsigned_ptrdiff)
321{
322 int rc;
323 ptrdiff_t pdu;
324
325 rc = sscanf("42", "%tu", &pdu);
326 PCUT_ASSERT_INT_EQUALS(1, rc);
327 PCUT_ASSERT_TRUE(pdu == 42);
328}
329
330/** Octal unsigned integer */
331PCUT_TEST(octal_unsigned)
332{
333 int rc;
334 unsigned u;
335
336 rc = sscanf("52", "%o", &u);
337 PCUT_ASSERT_INT_EQUALS(1, rc);
338 PCUT_ASSERT_TRUE(u == 052);
339}
340
341/** Hexadecimal unsigned integer */
342PCUT_TEST(hex_unsigned)
343{
344 int rc;
345 unsigned u;
346
347 rc = sscanf("2a", "%x", &u);
348 PCUT_ASSERT_INT_EQUALS(1, rc);
349 PCUT_ASSERT_TRUE(u == 0x2a);
350}
351
352/** Hexadecimal unsigned integer unsing alternate specifier */
353PCUT_TEST(hex_unsigned_cap_x)
354{
355 int rc;
356 unsigned u;
357
358 rc = sscanf("2a", "%X", &u);
359 PCUT_ASSERT_INT_EQUALS(1, rc);
360 PCUT_ASSERT_TRUE(u == 0x2a);
361}
362
363/** Uppercase hexadecimal unsigned integer */
364PCUT_TEST(uppercase_hex_unsigned)
365{
366 int rc;
367 unsigned u;
368
369 rc = sscanf("2A", "%x", &u);
370 PCUT_ASSERT_INT_EQUALS(1, rc);
371 PCUT_ASSERT_TRUE(u == 0x2a);
372}
373
374/** Make sure %x does not match 0x prefix */
375PCUT_TEST(hex_not_match_0x)
376{
377 int rc;
378 unsigned u;
379
380 rc = sscanf("0x1", "%x", &u);
381
382 PCUT_ASSERT_INT_EQUALS(1, rc);
383 PCUT_ASSERT_TRUE(u == 0);
384}
385
386/** Skipping whitespace */
387PCUT_TEST(skipws)
388{
389 int rc;
390 int i;
391
392 rc = sscanf(" \t\n42", "%d", &i);
393 PCUT_ASSERT_INT_EQUALS(1, rc);
394 PCUT_ASSERT_TRUE(i == 42);
395}
396
397/** Percentile conversion */
398PCUT_TEST(percentile)
399{
400 int rc;
401 int i;
402
403 rc = sscanf(" \t\n%42", "%%%d", &i);
404 PCUT_ASSERT_INT_EQUALS(1, rc);
405 PCUT_ASSERT_TRUE(i == 42);
406}
407
408/** Matching specific character */
409PCUT_TEST(match_spec_char)
410{
411 int rc;
412 int i;
413
414 rc = sscanf("x42", "x%d", &i);
415 PCUT_ASSERT_INT_EQUALS(1, rc);
416 PCUT_ASSERT_TRUE(i == 42);
417}
418
419/** Matching specific character should not skip whitespace */
420PCUT_TEST(match_char_noskipws)
421{
422 int rc;
423 int i;
424
425 rc = sscanf(" x42", "x%d", &i);
426 PCUT_ASSERT_INT_EQUALS(0, rc);
427}
428
429/** Skipping whitespace + match specific character */
430PCUT_TEST(skipws_match_char)
431{
432 int rc;
433 int i;
434
435 rc = sscanf(" x42", "\t\nx%d", &i);
436 PCUT_ASSERT_INT_EQUALS(1, rc);
437 PCUT_ASSERT_TRUE(i == 42);
438}
439
440/** Decimal with limited, but sufficient width */
441PCUT_TEST(dec_sufficient_lim_width)
442{
443 int rc;
444 int i;
445
446 rc = sscanf("42", "%2d", &i);
447 PCUT_ASSERT_INT_EQUALS(1, rc);
448 PCUT_ASSERT_TRUE(i == 42);
449}
450
451/** Decimal with limited, smaller width */
452PCUT_TEST(dec_smaller_width)
453{
454 int rc;
455 int i;
456
457 rc = sscanf("42", "%1d", &i);
458 PCUT_ASSERT_INT_EQUALS(1, rc);
459 PCUT_ASSERT_TRUE(i == 4);
460}
461
462/** Integer with hex prefix, format with limited, sufficient width */
463PCUT_TEST(int_hex_limited_width)
464{
465 int rc;
466 int i;
467
468 rc = sscanf("0x1", "%3i", &i);
469 PCUT_ASSERT_INT_EQUALS(1, rc);
470 PCUT_ASSERT_TRUE(i == 1);
471}
472
473/** Integer with hex prefix, format with limited, smaller width */
474PCUT_TEST(int_hex_small_width)
475{
476 int rc;
477 int i;
478
479 rc = sscanf("0x1", "%2i", &i);
480 PCUT_ASSERT_INT_EQUALS(1, rc);
481 PCUT_ASSERT_TRUE(i == 0);
482}
483
484/** Integer with octal prefix, format with limited, sufficient width */
485PCUT_TEST(int_oct_limited_width)
486{
487 int rc;
488 int i;
489
490 rc = sscanf("012", "%3i", &i);
491 PCUT_ASSERT_INT_EQUALS(1, rc);
492 PCUT_ASSERT_TRUE(i == 012);
493}
494
495/** Integer with octal prefix, format with limited, smaller width */
496PCUT_TEST(int_oct_smaller_width)
497{
498 int rc;
499 int i;
500
501 rc = sscanf("012", "%2i", &i);
502 PCUT_ASSERT_INT_EQUALS(1, rc);
503 PCUT_ASSERT_TRUE(i == 01);
504}
505
506/** Integer with octal prefix, format with width allowing just for 0 */
507PCUT_TEST(int_oct_tiny_width)
508{
509 int rc;
510 int i;
511
512 rc = sscanf("012", "%1i", &i);
513 PCUT_ASSERT_INT_EQUALS(1, rc);
514 PCUT_ASSERT_TRUE(i == 0);
515}
516
517/** Pointer */
518PCUT_TEST(pointer)
519{
520 int rc;
521 void *ptr;
522
523 rc = sscanf("0xABCDEF88", "%p", &ptr);
524 PCUT_ASSERT_INT_EQUALS(1, rc);
525 PCUT_ASSERT_TRUE(ptr == (void *)0xABCDEF88);
526}
527
528/** Single character */
529PCUT_TEST(single_char)
530{
531 int rc;
532 char c;
533
534 rc = sscanf("x", "%c", &c);
535 PCUT_ASSERT_INT_EQUALS(1, rc);
536 PCUT_ASSERT_TRUE(c == 'x');
537}
538
539/** Single whitespace character */
540PCUT_TEST(single_ws_char)
541{
542 int rc;
543 char c;
544
545 rc = sscanf("\t", "%c", &c);
546 PCUT_ASSERT_INT_EQUALS(1, rc);
547 PCUT_ASSERT_TRUE(c == '\t');
548}
549
550/** Multiple characters */
551PCUT_TEST(chars)
552{
553 int rc;
554 char chars[chars_size];
555
556 memset(chars, 'X', chars_size);
557 rc = sscanf("abc", "%3c", chars);
558 PCUT_ASSERT_INT_EQUALS(1, rc);
559 PCUT_ASSERT_TRUE(chars[0] == 'a');
560 PCUT_ASSERT_TRUE(chars[1] == 'b');
561 PCUT_ASSERT_TRUE(chars[2] == 'c');
562 PCUT_ASSERT_TRUE(chars[3] == 'X');
563}
564
565/** Fewer characters than requested */
566PCUT_TEST(fewer_chars)
567{
568 int rc;
569 char chars[chars_size];
570
571 memset(chars, 'X', chars_size);
572 rc = sscanf("abc", "%5c", chars);
573 PCUT_ASSERT_INT_EQUALS(1, rc);
574 PCUT_ASSERT_TRUE(chars[0] == 'a');
575 PCUT_ASSERT_TRUE(chars[1] == 'b');
576 PCUT_ASSERT_TRUE(chars[2] == 'c');
577 PCUT_ASSERT_TRUE(chars[3] == 'X');
578}
579
580/** Reading characters but no found */
581PCUT_TEST(chars_not_found)
582{
583 int rc;
584 char chars[chars_size];
585
586 memset(chars, 'X', chars_size);
587 rc = sscanf("", "%5c", chars);
588 PCUT_ASSERT_INT_EQUALS(EOF, rc);
589 PCUT_ASSERT_TRUE(chars[0] == 'X');
590}
591
592/** Multiple characters with suppressed assignment */
593PCUT_TEST(chars_noassign)
594{
595 int rc;
596 int n;
597
598 rc = sscanf("abc", "%*3c%n", &n);
599 PCUT_ASSERT_INT_EQUALS(0, rc);
600 PCUT_ASSERT_INT_EQUALS(3, n);
601}
602
603/** Multiple characters with memory allocation */
604PCUT_TEST(chars_malloc)
605{
606 int rc;
607 char *cp;
608
609 cp = NULL;
610 rc = sscanf("abc", "%m3c", &cp);
611 PCUT_ASSERT_INT_EQUALS(1, rc);
612 PCUT_ASSERT_NOT_NULL(cp);
613 PCUT_ASSERT_TRUE(cp[0] == 'a');
614 PCUT_ASSERT_TRUE(cp[1] == 'b');
615 PCUT_ASSERT_TRUE(cp[2] == 'c');
616 free(cp);
617}
618
619/** String of non-whitespace characters, unlimited width */
620PCUT_TEST(str)
621{
622 int rc;
623 char chars[chars_size];
624
625 memset(chars, 'X', chars_size);
626 rc = sscanf(" abc d", "%s", chars);
627 PCUT_ASSERT_INT_EQUALS(1, rc);
628 PCUT_ASSERT_TRUE(chars[0] == 'a');
629 PCUT_ASSERT_TRUE(chars[1] == 'b');
630 PCUT_ASSERT_TRUE(chars[2] == 'c');
631 PCUT_ASSERT_TRUE(chars[3] == '\0');
632 PCUT_ASSERT_TRUE(chars[4] == 'X');
633}
634
635/** String of non-whitespace characters, until the end */
636PCUT_TEST(str_till_end)
637{
638 int rc;
639 char chars[chars_size];
640
641 memset(chars, 'X', chars_size);
642 rc = sscanf(" abc", "%s", chars);
643 PCUT_ASSERT_INT_EQUALS(1, rc);
644 PCUT_ASSERT_TRUE(chars[0] == 'a');
645 PCUT_ASSERT_TRUE(chars[1] == 'b');
646 PCUT_ASSERT_TRUE(chars[2] == 'c');
647 PCUT_ASSERT_TRUE(chars[3] == '\0');
648 PCUT_ASSERT_TRUE(chars[4] == 'X');
649}
650
651/** String of non-whitespace characters, large enough width */
652PCUT_TEST(str_large_width)
653{
654 int rc;
655 char chars[chars_size];
656
657 memset(chars, 'X', chars_size);
658 rc = sscanf(" abc d", "%5s", chars);
659 PCUT_ASSERT_INT_EQUALS(1, rc);
660 PCUT_ASSERT_TRUE(chars[0] == 'a');
661 PCUT_ASSERT_TRUE(chars[1] == 'b');
662 PCUT_ASSERT_TRUE(chars[2] == 'c');
663 PCUT_ASSERT_TRUE(chars[3] == '\0');
664 PCUT_ASSERT_TRUE(chars[4] == 'X');
665}
666
667/** Want string of non-whitespace, but got only whitespace */
668PCUT_TEST(str_not_found)
669{
670 int rc;
671 char chars[chars_size];
672
673 memset(chars, 'X', chars_size);
674 rc = sscanf(" ", "%s", chars);
675 PCUT_ASSERT_INT_EQUALS(EOF, rc);
676 PCUT_ASSERT_TRUE(chars[0] == 'X');
677}
678
679/** String of non-whitespace characters, small width */
680PCUT_TEST(str_small_width)
681{
682 int rc;
683 char chars[chars_size];
684
685 memset(chars, 'X', chars_size);
686 rc = sscanf(" abc", "%2s", chars);
687 PCUT_ASSERT_INT_EQUALS(1, rc);
688 PCUT_ASSERT_TRUE(chars[0] == 'a');
689 PCUT_ASSERT_TRUE(chars[1] == 'b');
690 PCUT_ASSERT_TRUE(chars[2] == '\0');
691 PCUT_ASSERT_TRUE(chars[3] == 'X');
692}
693
694/** String of non-whitespace characters, assignment suppression */
695PCUT_TEST(str_noassign)
696{
697 int rc;
698 int n;
699
700 rc = sscanf(" abc d", "%*s%n", &n);
701 PCUT_ASSERT_INT_EQUALS(0, rc);
702 PCUT_ASSERT_INT_EQUALS(4, n);
703}
704
705/** String of non-whitespace characters, memory allocation */
706PCUT_TEST(str_malloc)
707{
708 int rc;
709 char *cp;
710
711 rc = sscanf(" abc d", "%ms", &cp);
712 PCUT_ASSERT_INT_EQUALS(1, rc);
713 PCUT_ASSERT_NOT_NULL(cp);
714 PCUT_ASSERT_TRUE(cp[0] == 'a');
715 PCUT_ASSERT_TRUE(cp[1] == 'b');
716 PCUT_ASSERT_TRUE(cp[2] == 'c');
717 PCUT_ASSERT_TRUE(cp[3] == '\0');
718 free(cp);
719}
720
721/** Set conversion without width specified terminating before the end */
722PCUT_TEST(set_convert)
723{
724 int rc;
725 char chars[chars_size];
726 int i;
727
728 memset(chars, 'X', chars_size);
729 rc = sscanf("abcd42", "%[abc]d%d", chars, &i);
730 PCUT_ASSERT_INT_EQUALS(2, rc);
731 PCUT_ASSERT_TRUE(chars[0] == 'a');
732 PCUT_ASSERT_TRUE(chars[1] == 'b');
733 PCUT_ASSERT_TRUE(chars[2] == 'c');
734 PCUT_ASSERT_TRUE(chars[3] == '\0');
735 PCUT_ASSERT_TRUE(chars[4] == 'X');
736 PCUT_ASSERT_TRUE(i == 42);
737}
738
739/** Set conversion without width specified, until the end */
740PCUT_TEST(set_till_end)
741{
742 int rc;
743 char chars[chars_size];
744
745 memset(chars, 'X', chars_size);
746 rc = sscanf("abc", "%[abc]", chars);
747 PCUT_ASSERT_INT_EQUALS(1, rc);
748 PCUT_ASSERT_TRUE(chars[0] == 'a');
749 PCUT_ASSERT_TRUE(chars[1] == 'b');
750 PCUT_ASSERT_TRUE(chars[2] == 'c');
751 PCUT_ASSERT_TRUE(chars[3] == '\0');
752 PCUT_ASSERT_TRUE(chars[4] == 'X');
753}
754
755/** Set conversion with larger width */
756PCUT_TEST(set_large_width)
757{
758 int rc;
759 char chars[chars_size];
760
761 memset(chars, 'X', chars_size);
762 rc = sscanf("abcd", "%5[abc]", chars);
763 PCUT_ASSERT_INT_EQUALS(1, rc);
764 PCUT_ASSERT_TRUE(chars[0] == 'a');
765 PCUT_ASSERT_TRUE(chars[1] == 'b');
766 PCUT_ASSERT_TRUE(chars[2] == 'c');
767 PCUT_ASSERT_TRUE(chars[3] == '\0');
768 PCUT_ASSERT_TRUE(chars[4] == 'X');
769}
770
771/** Set conversion with smaller width */
772PCUT_TEST(set_small_width)
773{
774 int rc;
775 char chars[chars_size];
776
777 memset(chars, 'X', chars_size);
778 rc = sscanf("abcd", "%3[abcd]", chars);
779 PCUT_ASSERT_INT_EQUALS(1, rc);
780 PCUT_ASSERT_TRUE(chars[0] == 'a');
781 PCUT_ASSERT_TRUE(chars[1] == 'b');
782 PCUT_ASSERT_TRUE(chars[2] == 'c');
783 PCUT_ASSERT_TRUE(chars[3] == '\0');
784 PCUT_ASSERT_TRUE(chars[4] == 'X');
785}
786
787/** Set conversion with negated scanset */
788PCUT_TEST(set_inverted)
789{
790 int rc;
791 char chars[chars_size];
792
793 memset(chars, 'X', chars_size);
794 rc = sscanf("abcd", "%[^d]", chars);
795 PCUT_ASSERT_INT_EQUALS(1, rc);
796 PCUT_ASSERT_TRUE(chars[0] == 'a');
797 PCUT_ASSERT_TRUE(chars[1] == 'b');
798 PCUT_ASSERT_TRUE(chars[2] == 'c');
799 PCUT_ASSERT_TRUE(chars[3] == '\0');
800 PCUT_ASSERT_TRUE(chars[4] == 'X');
801}
802
803/** Set conversion with ']' in scanset */
804PCUT_TEST(set_with_rbr)
805{
806 int rc;
807 char chars[chars_size];
808
809 memset(chars, 'X', chars_size);
810 rc = sscanf("]bcd", "%[]bc]", chars);
811 PCUT_ASSERT_INT_EQUALS(1, rc);
812 PCUT_ASSERT_TRUE(chars[0] == ']');
813 PCUT_ASSERT_TRUE(chars[1] == 'b');
814 PCUT_ASSERT_TRUE(chars[2] == 'c');
815 PCUT_ASSERT_TRUE(chars[3] == '\0');
816 PCUT_ASSERT_TRUE(chars[4] == 'X');
817}
818
819/** Set conversion with ']' in inverted scanset */
820PCUT_TEST(set_inverted_with_rbr)
821{
822 int rc;
823 char chars[chars_size];
824
825 memset(chars, 'X', chars_size);
826 rc = sscanf("abc]", "%[^]def]", chars);
827 PCUT_ASSERT_INT_EQUALS(1, rc);
828 PCUT_ASSERT_TRUE(chars[0] == 'a');
829 PCUT_ASSERT_TRUE(chars[1] == 'b');
830 PCUT_ASSERT_TRUE(chars[2] == 'c');
831 PCUT_ASSERT_TRUE(chars[3] == '\0');
832 PCUT_ASSERT_TRUE(chars[4] == 'X');
833}
834
835/** Set conversion with leading '-' in scanset */
836PCUT_TEST(set_with_leading_dash)
837{
838 int rc;
839 char chars[chars_size];
840
841 memset(chars, 'X', chars_size);
842 rc = sscanf("a-bc[", "%[-abc]", chars);
843 PCUT_ASSERT_INT_EQUALS(1, rc);
844 PCUT_ASSERT_TRUE(chars[0] == 'a');
845 PCUT_ASSERT_TRUE(chars[1] == '-');
846 PCUT_ASSERT_TRUE(chars[2] == 'b');
847 PCUT_ASSERT_TRUE(chars[3] == 'c');
848 PCUT_ASSERT_TRUE(chars[4] == '\0');
849 PCUT_ASSERT_TRUE(chars[5] == 'X');
850}
851
852/** Set conversion with trailing '-' in scanset */
853PCUT_TEST(set_with_trailing_dash)
854{
855 int rc;
856 char chars[chars_size];
857
858 memset(chars, 'X', chars_size);
859 rc = sscanf("a-bc]", "%[abc-]", chars);
860 PCUT_ASSERT_INT_EQUALS(1, rc);
861 PCUT_ASSERT_TRUE(chars[0] == 'a');
862 PCUT_ASSERT_TRUE(chars[1] == '-');
863 PCUT_ASSERT_TRUE(chars[2] == 'b');
864 PCUT_ASSERT_TRUE(chars[3] == 'c');
865 PCUT_ASSERT_TRUE(chars[4] == '\0');
866 PCUT_ASSERT_TRUE(chars[5] == 'X');
867}
868
869/** Set conversion with leading '-' in inverted scanset */
870PCUT_TEST(set_inverted_with_leading_dash)
871{
872 int rc;
873 char chars[chars_size];
874
875 memset(chars, 'X', chars_size);
876 rc = sscanf("def-", "%[^-abc]", chars);
877 PCUT_ASSERT_INT_EQUALS(1, rc);
878 PCUT_ASSERT_TRUE(chars[0] == 'd');
879 PCUT_ASSERT_TRUE(chars[1] == 'e');
880 PCUT_ASSERT_TRUE(chars[2] == 'f');
881 PCUT_ASSERT_TRUE(chars[3] == '\0');
882 PCUT_ASSERT_TRUE(chars[4] == 'X');
883}
884
885/** ']' after '^' in scanset does not lose meaning of scanset delimiter */
886PCUT_TEST(set_inverted_with_only_dash)
887{
888 int rc;
889 char chars[chars_size];
890
891 memset(chars, 'X', chars_size);
892 rc = sscanf("abc-", "%[^-]", chars);
893 PCUT_ASSERT_INT_EQUALS(1, rc);
894 PCUT_ASSERT_TRUE(chars[0] == 'a');
895 PCUT_ASSERT_TRUE(chars[1] == 'b');
896 PCUT_ASSERT_TRUE(chars[2] == 'c');
897 PCUT_ASSERT_TRUE(chars[3] == '\0');
898 PCUT_ASSERT_TRUE(chars[4] == 'X');
899}
900
901/** '^' after '-' in scanset does not have special meaning */
902PCUT_TEST(set_inverted_with_dash_caret)
903{
904 int rc;
905 char chars[chars_size];
906
907 memset(chars, 'X', chars_size);
908 rc = sscanf("-^a", "%[-^a]", chars);
909 PCUT_ASSERT_INT_EQUALS(1, rc);
910 PCUT_ASSERT_TRUE(chars[0] == '-');
911 PCUT_ASSERT_TRUE(chars[1] == '^');
912 PCUT_ASSERT_TRUE(chars[2] == 'a');
913 PCUT_ASSERT_TRUE(chars[3] == '\0');
914 PCUT_ASSERT_TRUE(chars[4] == 'X');
915}
916
917/** Set conversion with range (GNU extension) */
918PCUT_TEST(set_with_range)
919{
920 int rc;
921 char chars[chars_size];
922
923 memset(chars, 'X', chars_size);
924 rc = sscanf("abc]", "%[a-c]", chars);
925 PCUT_ASSERT_INT_EQUALS(1, rc);
926 PCUT_ASSERT_TRUE(chars[0] == 'a');
927 PCUT_ASSERT_TRUE(chars[1] == 'b');
928 PCUT_ASSERT_TRUE(chars[2] == 'c');
929 PCUT_ASSERT_TRUE(chars[3] == '\0');
930 PCUT_ASSERT_TRUE(chars[4] == 'X');
931}
932
933/** Set conversion with range (GNU extension) in inverted scanset */
934PCUT_TEST(set_inverted_with_range)
935{
936 int rc;
937 char chars[chars_size];
938
939 memset(chars, 'X', chars_size);
940 rc = sscanf("defb", "%[^a-c]", chars);
941 PCUT_ASSERT_INT_EQUALS(1, rc);
942 PCUT_ASSERT_TRUE(chars[0] == 'd');
943 PCUT_ASSERT_TRUE(chars[1] == 'e');
944 PCUT_ASSERT_TRUE(chars[2] == 'f');
945 PCUT_ASSERT_TRUE(chars[3] == '\0');
946 PCUT_ASSERT_TRUE(chars[4] == 'X');
947}
948
949/** Set conversion with assignment suppression */
950PCUT_TEST(set_noassign)
951{
952 int rc;
953 int n;
954
955 rc = sscanf("abcd42", "%*[abc]%n", &n);
956 PCUT_ASSERT_INT_EQUALS(0, rc);
957 PCUT_ASSERT_INT_EQUALS(3, n);
958}
959
960/** Set conversion with memory allocation */
961PCUT_TEST(set_malloc)
962{
963 int rc;
964 char *cp;
965
966 cp = NULL;
967 rc = sscanf("abcd42", "%m[abcd]", &cp);
968 PCUT_ASSERT_INT_EQUALS(1, rc);
969 PCUT_ASSERT_NOT_NULL(cp);
970 PCUT_ASSERT_TRUE(cp[0] == 'a');
971 PCUT_ASSERT_TRUE(cp[1] == 'b');
972 PCUT_ASSERT_TRUE(cp[2] == 'c');
973 PCUT_ASSERT_TRUE(cp[3] == 'd');
974 PCUT_ASSERT_TRUE(cp[4] == '\0');
975 free(cp);
976}
977
978/** Decimal integer with suppressed assignment */
979PCUT_TEST(dec_int_noassign)
980{
981 int rc;
982 int n;
983
984 rc = sscanf("42", "%*d%n", &n);
985 PCUT_ASSERT_INT_EQUALS(0, rc);
986 PCUT_ASSERT_INT_EQUALS(2, n);
987}
988
989/** Count of characters read */
990PCUT_TEST(count_chars)
991{
992 int rc;
993 char chars[chars_size];
994 int n;
995
996 memset(chars, 'X', chars_size);
997 rc = sscanf("abcd", "%3c%n", chars, &n);
998 PCUT_ASSERT_INT_EQUALS(1, rc);
999 PCUT_ASSERT_TRUE(chars[0] == 'a');
1000 PCUT_ASSERT_TRUE(chars[1] == 'b');
1001 PCUT_ASSERT_TRUE(chars[2] == 'c');
1002 PCUT_ASSERT_TRUE(chars[3] == 'X');
1003 PCUT_ASSERT_INT_EQUALS(3, n);
1004}
1005
1006/** Float with just integer part */
1007PCUT_TEST(float_intpart_only)
1008{
1009 int rc;
1010 float f;
1011
1012 rc = sscanf("42", "%f", &f);
1013 PCUT_ASSERT_INT_EQUALS(1, rc);
1014 PCUT_ASSERT_TRUE(f == 42.0);
1015}
1016
1017/** Double with just integer part */
1018PCUT_TEST(double_intpart_only)
1019{
1020 int rc;
1021 double d;
1022
1023 rc = sscanf("42", "%lf", &d);
1024 PCUT_ASSERT_INT_EQUALS(1, rc);
1025 PCUT_ASSERT_TRUE(d == 42.0);
1026}
1027
1028/** Long double with just integer part */
1029PCUT_TEST(ldouble_intpart_only)
1030{
1031 int rc;
1032 long double ld;
1033
1034 rc = sscanf("42", "%Lf", &ld);
1035 PCUT_ASSERT_INT_EQUALS(1, rc);
1036 PCUT_ASSERT_TRUE(ld == 42.0);
1037}
1038
1039/** Float with just hexadecimal integer part */
1040PCUT_TEST(float_hex_intpart_only)
1041{
1042 int rc;
1043 float f;
1044
1045 rc = sscanf("0x2a", "%f", &f);
1046 PCUT_ASSERT_INT_EQUALS(1, rc);
1047 PCUT_ASSERT_TRUE(f == 0x2a.0p0);
1048}
1049
1050/** Float with sign and integer part */
1051PCUT_TEST(float_sign_intpart)
1052{
1053 int rc;
1054 float f;
1055
1056 rc = sscanf("-42", "%f", &f);
1057 PCUT_ASSERT_INT_EQUALS(1, rc);
1058 PCUT_ASSERT_TRUE(f == -42.0);
1059}
1060
1061/** Float with integer and fractional part */
1062PCUT_TEST(float_intpart_fract)
1063{
1064 int rc;
1065 float f;
1066
1067 rc = sscanf("4.2", "%f", &f);
1068 PCUT_ASSERT_INT_EQUALS(1, rc);
1069 /* 1/10 is not exactly representable in binary floating point */
1070 PCUT_ASSERT_TRUE(f > 4.199);
1071 PCUT_ASSERT_TRUE(f < 4.201);
1072}
1073
1074/** Float with integer part and unsigned exponent */
1075PCUT_TEST(float_intpart_exp)
1076{
1077 int rc;
1078 float f;
1079
1080 rc = sscanf("42e1", "%f", &f);
1081 PCUT_ASSERT_INT_EQUALS(1, rc);
1082 PCUT_ASSERT_TRUE(f == 420.0);
1083}
1084
1085/** Float with integer part and positive exponent */
1086PCUT_TEST(float_intpart_posexp)
1087{
1088 int rc;
1089 float f;
1090 rc = sscanf("42e+1", "%f", &f);
1091 PCUT_ASSERT_INT_EQUALS(1, rc);
1092 PCUT_ASSERT_TRUE(f == 420.0);
1093}
1094
1095/** Float with integer part and negative exponent */
1096PCUT_TEST(float_intpart_negexp)
1097{
1098 int rc;
1099 float f;
1100
1101 rc = sscanf("42e-1", "%f", &f);
1102 PCUT_ASSERT_INT_EQUALS(1, rc);
1103 /* 1/10 is not exactly representable in binary floating point */
1104 PCUT_ASSERT_TRUE(f > 4.199);
1105 PCUT_ASSERT_TRUE(f < 4.201);
1106}
1107
1108/** Float with integer, fractional parts and unsigned exponent */
1109PCUT_TEST(float_intpart_fract_exp)
1110{
1111 int rc;
1112 float f;
1113
1114 rc = sscanf("4.2e1", "%f", &f);
1115 PCUT_ASSERT_INT_EQUALS(1, rc);
1116 PCUT_ASSERT_TRUE(f == 42.0);
1117}
1118
1119/** Hexadecimal float with integer and fractional part */
1120PCUT_TEST(hexfloat_intpart_fract)
1121{
1122 int rc;
1123 float f;
1124
1125 rc = sscanf("0x2.a", "%f", &f);
1126 PCUT_ASSERT_INT_EQUALS(1, rc);
1127 PCUT_ASSERT_TRUE(f == 0x2.ap0);
1128}
1129
1130/** Hexadecimal float with integer part and unsigned exponent */
1131PCUT_TEST(hexfloat_intpart_exp)
1132{
1133 int rc;
1134 float f;
1135
1136 rc = sscanf("0x2ap1", "%f", &f);
1137 PCUT_ASSERT_INT_EQUALS(1, rc);
1138 PCUT_ASSERT_TRUE(f == 0x2ap1);
1139}
1140
1141/** Hexadecimal float with integer part and negative exponent */
1142PCUT_TEST(hexfloat_intpart_negexp)
1143{
1144 int rc;
1145 float f;
1146
1147 rc = sscanf("0x2ap-1", "%f", &f);
1148 PCUT_ASSERT_INT_EQUALS(1, rc);
1149 PCUT_ASSERT_TRUE(f == 0x2ap-1);
1150}
1151
1152/** Hexadecimal float with integer, fractional parts and unsigned exponent */
1153PCUT_TEST(hexfloat_intpart_fract_exp)
1154{
1155 int rc;
1156 float f;
1157
1158 rc = sscanf("0x2.ap4", "%f", &f);
1159 PCUT_ASSERT_INT_EQUALS(1, rc);
1160 PCUT_ASSERT_TRUE(f == 0x2.ap4);
1161}
1162
1163/** Float with just integer part and limited width */
1164PCUT_TEST(float_intpart_limwidth)
1165{
1166 int rc;
1167 float f;
1168
1169 rc = sscanf("1234", "%3f", &f);
1170 PCUT_ASSERT_INT_EQUALS(1, rc);
1171 PCUT_ASSERT_TRUE(f == 123.0);
1172}
1173
1174/** Float with integer, fractional part and limited width */
1175PCUT_TEST(float_intpart_fract_limwidth)
1176{
1177 int rc;
1178 float f;
1179
1180 rc = sscanf("12.34", "%4f", &f);
1181 PCUT_ASSERT_INT_EQUALS(1, rc);
1182 /* 1/10 is not exactly representable in binary floating point */
1183 PCUT_ASSERT_TRUE(f > 12.29);
1184 PCUT_ASSERT_TRUE(f < 12.31);
1185}
1186
1187/** Float with width only enough to cover an integral part */
1188PCUT_TEST(float_width_for_only_intpart)
1189{
1190 int rc;
1191 float f;
1192
1193 rc = sscanf("12.34", "%3f", &f);
1194 PCUT_ASSERT_INT_EQUALS(1, rc);
1195 PCUT_ASSERT_TRUE(f == 12.0);
1196}
1197
1198/** Float with width too small to cover the exponent number */
1199PCUT_TEST(float_width_small_for_expnum)
1200{
1201 int rc;
1202 float f;
1203
1204 rc = sscanf("12.34e+2", "%7f", &f);
1205 PCUT_ASSERT_INT_EQUALS(1, rc);
1206 /* 1/10 is not exactly representable in binary floating point */
1207 PCUT_ASSERT_TRUE(f > 12.339);
1208 PCUT_ASSERT_TRUE(f < 12.341);
1209}
1210
1211/** Float with width too small to cover the exponent sign and number */
1212PCUT_TEST(float_width_small_for_expsignum)
1213{
1214 int rc;
1215 float f;
1216
1217 rc = sscanf("12.34e+2", "%6f", &f);
1218 PCUT_ASSERT_INT_EQUALS(1, rc);
1219 /* 1/10 is not exactly representable in binary floating point */
1220 PCUT_ASSERT_TRUE(f > 12.339);
1221 PCUT_ASSERT_TRUE(f < 12.341);
1222}
1223
1224/** Float with width too small to cover the exponent part */
1225PCUT_TEST(float_width_small_for_exp)
1226{
1227 int rc;
1228 float f;
1229
1230 rc = sscanf("12.34e+2", "%5f", &f);
1231 PCUT_ASSERT_INT_EQUALS(1, rc);
1232 /* 1/10 is not exactly representable in binary floating point */
1233 PCUT_ASSERT_TRUE(f > 12.339);
1234 PCUT_ASSERT_TRUE(f < 12.341);
1235}
1236
1237/** Float using alternate form 'F' */
1238PCUT_TEST(float_cap_f)
1239{
1240 int rc;
1241 float f;
1242
1243 rc = sscanf("42e1", "%F", &f);
1244 PCUT_ASSERT_INT_EQUALS(1, rc);
1245 PCUT_ASSERT_TRUE(f == 420.0);
1246}
1247
1248/** Float using alternate form 'a' */
1249PCUT_TEST(float_a)
1250{
1251 int rc;
1252 float f;
1253
1254 rc = sscanf("42e1", "%a", &f);
1255 PCUT_ASSERT_INT_EQUALS(1, rc);
1256 PCUT_ASSERT_TRUE(f == 420.0);
1257}
1258
1259/** Float using alternate form 'e' */
1260PCUT_TEST(float_e)
1261{
1262 int rc;
1263 float f;
1264
1265 rc = sscanf("42e1", "%e", &f);
1266 PCUT_ASSERT_INT_EQUALS(1, rc);
1267 PCUT_ASSERT_TRUE(f == 420.0);
1268}
1269
1270/** Float using alternate form 'g' */
1271PCUT_TEST(float_g)
1272{
1273 int rc;
1274 float f;
1275
1276 rc = sscanf("42e1", "%g", &f);
1277 PCUT_ASSERT_INT_EQUALS(1, rc);
1278 PCUT_ASSERT_TRUE(f == 420.0);
1279}
1280
1281/** Float using alternate form 'A' */
1282PCUT_TEST(float_cap_a)
1283{
1284 int rc;
1285 float f;
1286
1287 rc = sscanf("42e1", "%A", &f);
1288 PCUT_ASSERT_INT_EQUALS(1, rc);
1289 PCUT_ASSERT_TRUE(f == 420.0);
1290}
1291
1292/** Float using alternate form 'E' */
1293PCUT_TEST(float_cap_e)
1294{
1295 int rc;
1296 float f;
1297
1298 rc = sscanf("42e1", "%E", &f);
1299 PCUT_ASSERT_INT_EQUALS(1, rc);
1300 PCUT_ASSERT_TRUE(f == 420.0);
1301}
1302
1303/** Float using alternate form 'G' */
1304PCUT_TEST(float_cap_g)
1305{
1306 int rc;
1307 float f;
1308
1309 rc = sscanf("42e1", "%G", &f);
1310 PCUT_ASSERT_INT_EQUALS(1, rc);
1311 PCUT_ASSERT_TRUE(f == 420.0);
1312}
1313
1314PCUT_EXPORT(scanf);
Note: See TracBrowser for help on using the repository browser.