1 //===-- Unittests for the basic scanf converters --------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/CPP/string_view.h"
10 #include "src/stdio/scanf_core/converter.h"
11 #include "src/stdio/scanf_core/core_structs.h"
12 #include "src/stdio/scanf_core/reader.h"
14 #include "test/UnitTest/Test.h"
16 TEST(LlvmLibcScanfConverterTest
, RawMatchBasic
) {
17 const char *str
= "abcdef";
18 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader
{str
, sizeof(str
)};
19 LIBC_NAMESPACE::scanf_core::Reader
reader(&str_reader
);
21 // Reading "abc" should succeed.
22 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "abc"),
23 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
24 ASSERT_EQ(reader
.chars_read(), size_t(3));
26 // Reading nothing should succeed and not advance.
27 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, ""),
28 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
29 ASSERT_EQ(reader
.chars_read(), size_t(3));
31 // Reading a space where there is none should succeed and not advance.
32 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, " "),
33 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
34 ASSERT_EQ(reader
.chars_read(), size_t(3));
36 // Reading "d" should succeed and advance by 1.
37 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "d"),
38 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
39 ASSERT_EQ(reader
.chars_read(), size_t(4));
41 // Reading "z" should fail and not advance.
42 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "z"),
43 static_cast<int>(LIBC_NAMESPACE::scanf_core::MATCHING_FAILURE
));
44 ASSERT_EQ(reader
.chars_read(), size_t(4));
46 // Reading "efgh" should fail but advance to the end.
47 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "efgh"),
48 static_cast<int>(LIBC_NAMESPACE::scanf_core::MATCHING_FAILURE
));
49 ASSERT_EQ(reader
.chars_read(), size_t(6));
52 TEST(LlvmLibcScanfConverterTest
, RawMatchSpaces
) {
53 const char *str
= " a \t\n b cd";
54 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader
{str
, sizeof(str
)};
55 LIBC_NAMESPACE::scanf_core::Reader
reader(&str_reader
);
57 // Reading "a" should fail and not advance.
58 // Since there's nothing in the format string (the second argument to
59 // raw_match) to match the space in the buffer it isn't consumed.
60 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "a"),
61 static_cast<int>(LIBC_NAMESPACE::scanf_core::MATCHING_FAILURE
));
62 ASSERT_EQ(reader
.chars_read(), size_t(0));
64 // Reading " \t\n " should succeed and advance past the space.
65 // Any number of space characters in the format string match 0 or more space
66 // characters in the buffer.
67 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, " \t\n "),
68 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
69 ASSERT_EQ(reader
.chars_read(), size_t(1));
71 // Reading "ab" should fail and only advance past the a
72 // The a characters match, but the format string doesn't have anything to
73 // consume the spaces in the buffer, so it fails.
74 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "ab"),
75 static_cast<int>(LIBC_NAMESPACE::scanf_core::MATCHING_FAILURE
));
76 ASSERT_EQ(reader
.chars_read(), size_t(2));
78 // Reading " b" should succeed and advance past the b
79 // Any number of space characters in the format string matches 0 or more space
80 // characters in the buffer.
81 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, " b"),
82 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
83 ASSERT_EQ(reader
.chars_read(), size_t(7));
85 // Reading "\t" should succeed and advance past the spaces to the c
86 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "\t"),
87 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
88 ASSERT_EQ(reader
.chars_read(), size_t(10));
90 // Reading "c d" should succeed and advance past the d.
91 // Here the space character in the format string is matching 0 space
92 // characters in the buffer.
93 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::raw_match(&reader
, "c d"),
94 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
95 ASSERT_EQ(reader
.chars_read(), size_t(12));
98 TEST(LlvmLibcScanfConverterTest
, StringConvSimple
) {
99 const char *str
= "abcDEF123 654LKJihg";
101 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader
{str
, sizeof(str
)};
102 LIBC_NAMESPACE::scanf_core::Reader
reader(&str_reader
);
104 LIBC_NAMESPACE::scanf_core::FormatSection conv
;
105 conv
.has_conv
= true;
106 conv
.conv_name
= 's';
107 conv
.output_ptr
= result
;
109 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
110 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
111 ASSERT_EQ(reader
.chars_read(), size_t(9));
112 ASSERT_STREQ(result
, "abcDEF123");
114 //%s skips all spaces before beginning to read.
115 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
116 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
117 ASSERT_EQ(reader
.chars_read(), size_t(19));
118 ASSERT_STREQ(result
, "654LKJihg");
121 TEST(LlvmLibcScanfConverterTest
, StringConvNoWrite
) {
122 const char *str
= "abcDEF123 654LKJihg";
123 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader
{str
, sizeof(str
)};
124 LIBC_NAMESPACE::scanf_core::Reader
reader(&str_reader
);
126 LIBC_NAMESPACE::scanf_core::FormatSection conv
;
127 conv
.has_conv
= true;
128 conv
.conv_name
= 's';
129 conv
.flags
= LIBC_NAMESPACE::scanf_core::NO_WRITE
;
131 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
132 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
133 ASSERT_EQ(reader
.chars_read(), size_t(9));
135 //%s skips all spaces before beginning to read.
136 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
137 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
138 ASSERT_EQ(reader
.chars_read(), size_t(19));
141 TEST(LlvmLibcScanfConverterTest
, StringConvWidth
) {
142 const char *str
= "abcDEF123 654LKJihg";
144 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader
{str
, sizeof(str
)};
145 LIBC_NAMESPACE::scanf_core::Reader
reader(&str_reader
);
147 LIBC_NAMESPACE::scanf_core::FormatSection conv
;
148 conv
.has_conv
= true;
149 conv
.conv_name
= 's';
150 conv
.max_width
= 5; // this means the result takes up 6 characters (with \0).
151 conv
.output_ptr
= result
;
153 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
154 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
155 ASSERT_EQ(reader
.chars_read(), size_t(5));
156 ASSERT_STREQ(result
, "abcDE");
158 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
159 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
160 ASSERT_EQ(reader
.chars_read(), size_t(9));
161 ASSERT_STREQ(result
, "F123");
163 //%s skips all spaces before beginning to read.
164 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
165 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
166 ASSERT_EQ(reader
.chars_read(), size_t(15));
167 ASSERT_STREQ(result
, "654LK");
169 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
170 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
171 ASSERT_EQ(reader
.chars_read(), size_t(19));
172 ASSERT_STREQ(result
, "Jihg");
175 TEST(LlvmLibcScanfConverterTest
, CharsConv
) {
176 const char *str
= "abcDEF123 654LKJihg MNOpqr&*(";
178 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader
{str
, sizeof(str
)};
179 LIBC_NAMESPACE::scanf_core::Reader
reader(&str_reader
);
181 LIBC_NAMESPACE::scanf_core::FormatSection conv
;
182 conv
.has_conv
= true;
183 conv
.conv_name
= 'c';
184 conv
.output_ptr
= result
;
186 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
187 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
188 ASSERT_EQ(reader
.chars_read(), size_t(1));
189 ASSERT_EQ(result
[0], 'a');
191 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
192 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
193 ASSERT_EQ(reader
.chars_read(), size_t(2));
194 ASSERT_EQ(result
[0], 'b');
196 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
197 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
198 ASSERT_EQ(reader
.chars_read(), size_t(3));
199 ASSERT_EQ(result
[0], 'c');
201 // Switch from character by character to 8 at a time.
203 LIBC_NAMESPACE::cpp::string_view
result_view(result
, 8);
205 //%c doesn't stop on spaces.
206 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
207 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
208 ASSERT_EQ(reader
.chars_read(), size_t(11));
209 ASSERT_EQ(result_view
, LIBC_NAMESPACE::cpp::string_view("DEF123 6", 8));
211 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
212 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
213 ASSERT_EQ(reader
.chars_read(), size_t(19));
214 ASSERT_EQ(result_view
, LIBC_NAMESPACE::cpp::string_view("54LKJihg", 8));
216 //%c also doesn't skip spaces at the start.
217 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
218 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
219 ASSERT_EQ(reader
.chars_read(), size_t(27));
220 ASSERT_EQ(result_view
, LIBC_NAMESPACE::cpp::string_view(" MNOpqr&", 8));
222 //%c will stop on a null byte though.
223 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
224 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
225 ASSERT_EQ(reader
.chars_read(), size_t(29));
226 ASSERT_EQ(LIBC_NAMESPACE::cpp::string_view(result
, 2),
227 LIBC_NAMESPACE::cpp::string_view("*(", 2));
230 TEST(LlvmLibcScanfConverterTest
, ScansetConv
) {
231 const char *str
= "abcDEF[123] 654LKJihg";
233 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader
{str
, sizeof(str
)};
234 LIBC_NAMESPACE::scanf_core::Reader
reader(&str_reader
);
236 LIBC_NAMESPACE::scanf_core::FormatSection conv
;
237 conv
.has_conv
= true;
238 conv
.conv_name
= '[';
239 conv
.output_ptr
= result
;
241 LIBC_NAMESPACE::cpp::bitset
<256> bitset1
;
242 bitset1
.set_range('a', 'c');
243 bitset1
.set_range('D', 'F');
244 bitset1
.set_range('1', '6');
248 conv
.scan_set
= bitset1
;
250 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
251 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
252 ASSERT_EQ(reader
.chars_read(), size_t(11));
253 ASSERT_EQ(LIBC_NAMESPACE::cpp::string_view(result
, 11),
254 LIBC_NAMESPACE::cpp::string_view("abcDEF[123]", 11));
256 // The scanset conversion doesn't consume leading spaces. If it did it would
257 // return "654" here.
258 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
259 static_cast<int>(LIBC_NAMESPACE::scanf_core::MATCHING_FAILURE
));
260 ASSERT_EQ(reader
.chars_read(), size_t(11));
262 // This set is everything except for a-g.
263 LIBC_NAMESPACE::cpp::bitset
<256> bitset2
;
264 bitset2
.set_range('a', 'g');
266 conv
.scan_set
= bitset2
;
270 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
271 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
272 ASSERT_EQ(reader
.chars_read(), size_t(16));
273 ASSERT_EQ(LIBC_NAMESPACE::cpp::string_view(result
, 5),
274 LIBC_NAMESPACE::cpp::string_view(" 654L", 5));
276 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
277 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
278 ASSERT_EQ(reader
.chars_read(), size_t(20));
279 ASSERT_EQ(LIBC_NAMESPACE::cpp::string_view(result
, 4),
280 LIBC_NAMESPACE::cpp::string_view("KJih", 4));
282 // This set is g and '\0'.
283 LIBC_NAMESPACE::cpp::bitset
<256> bitset3
;
286 conv
.scan_set
= bitset3
;
288 // Even though '\0' is in the scanset, it should still stop on it.
289 ASSERT_EQ(LIBC_NAMESPACE::scanf_core::convert(&reader
, conv
),
290 static_cast<int>(LIBC_NAMESPACE::scanf_core::READ_OK
));
291 ASSERT_EQ(reader
.chars_read(), size_t(21));
292 ASSERT_EQ(LIBC_NAMESPACE::cpp::string_view(result
, 1),
293 LIBC_NAMESPACE::cpp::string_view("g", 1));