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

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

Replace some license headers with SPDX identifier

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

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