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

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

Fix vertical spacing with new Ccheck revision.

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