1 //===-- Unittests for the basic scanf converters --------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 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" 13 14 #include "test/UnitTest/Test.h" 15 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); 20 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)); 25 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)); 30 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)); 35 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)); 40 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)); 45 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)); 50 } 51 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); 56 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)); 63 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)); 70 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)); 77 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)); 84 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)); 89 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)); 96 } 97 98 TEST(LlvmLibcScanfConverterTest, StringConvSimple) { 99 const char *str = "abcDEF123 654LKJihg"; 100 char result[20]; 101 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader{str, sizeof(str)}; 102 LIBC_NAMESPACE::scanf_core::Reader reader(&str_reader); 103 104 LIBC_NAMESPACE::scanf_core::FormatSection conv; 105 conv.has_conv = true; 106 conv.conv_name = 's'; 107 conv.output_ptr = result; 108 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"); 113 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"); 119 } 120 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); 125 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; 130 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)); 134 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)); 139 } 140 141 TEST(LlvmLibcScanfConverterTest, StringConvWidth) { 142 const char *str = "abcDEF123 654LKJihg"; 143 char result[6]; 144 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader{str, sizeof(str)}; 145 LIBC_NAMESPACE::scanf_core::Reader reader(&str_reader); 146 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; 152 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"); 157 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"); 162 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"); 168 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"); 173 } 174 175 TEST(LlvmLibcScanfConverterTest, CharsConv) { 176 const char *str = "abcDEF123 654LKJihg MNOpqr&*("; 177 char result[20]; 178 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader{str, sizeof(str)}; 179 LIBC_NAMESPACE::scanf_core::Reader reader(&str_reader); 180 181 LIBC_NAMESPACE::scanf_core::FormatSection conv; 182 conv.has_conv = true; 183 conv.conv_name = 'c'; 184 conv.output_ptr = result; 185 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'); 190 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'); 195 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'); 200 201 // Switch from character by character to 8 at a time. 202 conv.max_width = 8; 203 LIBC_NAMESPACE::cpp::string_view result_view(result, 8); 204 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)); 210 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)); 215 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)); 221 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)); 228 } 229 230 TEST(LlvmLibcScanfConverterTest, ScansetConv) { 231 const char *str = "abcDEF[123] 654LKJihg"; 232 char result[20]; 233 LIBC_NAMESPACE::scanf_core::ReadBuffer str_reader{str, sizeof(str)}; 234 LIBC_NAMESPACE::scanf_core::Reader reader(&str_reader); 235 236 LIBC_NAMESPACE::scanf_core::FormatSection conv; 237 conv.has_conv = true; 238 conv.conv_name = '['; 239 conv.output_ptr = result; 240 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'); 245 bitset1.set('['); 246 bitset1.set(']'); 247 248 conv.scan_set = bitset1; 249 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)); 255 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)); 261 262 // This set is everything except for a-g. 263 LIBC_NAMESPACE::cpp::bitset<256> bitset2; 264 bitset2.set_range('a', 'g'); 265 bitset2.flip(); 266 conv.scan_set = bitset2; 267 268 conv.max_width = 5; 269 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)); 275 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)); 281 282 // This set is g and '\0'. 283 LIBC_NAMESPACE::cpp::bitset<256> bitset3; 284 bitset3.set('g'); 285 bitset3.set('\0'); 286 conv.scan_set = bitset3; 287 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)); 294 } 295