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

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

Add actual test for using range in scanf.

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