1 | //===-- Unittests for the printf Converter --------------------------------===// |
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/stdio/printf_core/converter.h" |
10 | #include "src/stdio/printf_core/core_structs.h" |
11 | #include "src/stdio/printf_core/writer.h" |
12 | |
13 | #include "test/UnitTest/Test.h" |
14 | |
15 | class LlvmLibcPrintfConverterTest : public LIBC_NAMESPACE::testing::Test { |
16 | protected: |
17 | // void SetUp() override {} |
18 | // void TearDown() override {} |
19 | |
20 | char str[60]; |
21 | LIBC_NAMESPACE::printf_core::WriteBuffer< |
22 | LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> |
23 | wb = LIBC_NAMESPACE::printf_core::WriteBuffer< |
24 | LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>( |
25 | str, sizeof(str) - 1); |
26 | LIBC_NAMESPACE::printf_core::Writer< |
27 | LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> |
28 | writer = LIBC_NAMESPACE::printf_core::Writer(wb); |
29 | }; |
30 | |
31 | TEST_F(LlvmLibcPrintfConverterTest, SimpleRawConversion) { |
32 | LIBC_NAMESPACE::printf_core::FormatSection raw_section; |
33 | raw_section.has_conv = false; |
34 | raw_section.raw_string = "abc" ; |
35 | |
36 | LIBC_NAMESPACE::printf_core::convert(&writer, raw_section); |
37 | |
38 | wb.buff[wb.buff_cur] = '\0'; |
39 | |
40 | ASSERT_STREQ(str, "abc" ); |
41 | ASSERT_EQ(writer.get_chars_written(), 3); |
42 | } |
43 | |
44 | TEST_F(LlvmLibcPrintfConverterTest, PercentConversion) { |
45 | LIBC_NAMESPACE::printf_core::FormatSection simple_conv; |
46 | simple_conv.has_conv = true; |
47 | simple_conv.raw_string = "%%" ; |
48 | simple_conv.conv_name = '%'; |
49 | |
50 | LIBC_NAMESPACE::printf_core::convert(&writer, simple_conv); |
51 | |
52 | wb.buff[wb.buff_cur] = '\0'; |
53 | |
54 | ASSERT_STREQ(str, "%" ); |
55 | ASSERT_EQ(writer.get_chars_written(), 1); |
56 | } |
57 | |
58 | TEST_F(LlvmLibcPrintfConverterTest, CharConversionSimple) { |
59 | LIBC_NAMESPACE::printf_core::FormatSection simple_conv; |
60 | simple_conv.has_conv = true; |
61 | // If has_conv is true, the raw string is ignored. They are not being parsed |
62 | // and match the actual conversion taking place so that you can compare these |
63 | // tests with other implmentations. The raw strings are completely optional. |
64 | simple_conv.raw_string = "%c" ; |
65 | simple_conv.conv_name = 'c'; |
66 | simple_conv.conv_val_raw = 'D'; |
67 | |
68 | LIBC_NAMESPACE::printf_core::convert(&writer, simple_conv); |
69 | |
70 | wb.buff[wb.buff_cur] = '\0'; |
71 | |
72 | ASSERT_STREQ(str, "D" ); |
73 | ASSERT_EQ(writer.get_chars_written(), 1); |
74 | } |
75 | |
76 | TEST_F(LlvmLibcPrintfConverterTest, CharConversionRightJustified) { |
77 | LIBC_NAMESPACE::printf_core::FormatSection right_justified_conv; |
78 | right_justified_conv.has_conv = true; |
79 | right_justified_conv.raw_string = "%4c" ; |
80 | right_justified_conv.conv_name = 'c'; |
81 | right_justified_conv.min_width = 4; |
82 | right_justified_conv.conv_val_raw = 'E'; |
83 | LIBC_NAMESPACE::printf_core::convert(&writer, right_justified_conv); |
84 | |
85 | wb.buff[wb.buff_cur] = '\0'; |
86 | |
87 | ASSERT_STREQ(str, " E" ); |
88 | ASSERT_EQ(writer.get_chars_written(), 4); |
89 | } |
90 | |
91 | TEST_F(LlvmLibcPrintfConverterTest, CharConversionLeftJustified) { |
92 | LIBC_NAMESPACE::printf_core::FormatSection left_justified_conv; |
93 | left_justified_conv.has_conv = true; |
94 | left_justified_conv.raw_string = "%-4c" ; |
95 | left_justified_conv.conv_name = 'c'; |
96 | left_justified_conv.flags = |
97 | LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED; |
98 | left_justified_conv.min_width = 4; |
99 | left_justified_conv.conv_val_raw = 'F'; |
100 | LIBC_NAMESPACE::printf_core::convert(&writer, left_justified_conv); |
101 | |
102 | wb.buff[wb.buff_cur] = '\0'; |
103 | |
104 | ASSERT_STREQ(str, "F " ); |
105 | ASSERT_EQ(writer.get_chars_written(), 4); |
106 | } |
107 | |
108 | TEST_F(LlvmLibcPrintfConverterTest, StringConversionSimple) { |
109 | |
110 | LIBC_NAMESPACE::printf_core::FormatSection simple_conv; |
111 | simple_conv.has_conv = true; |
112 | simple_conv.raw_string = "%s" ; |
113 | simple_conv.conv_name = 's'; |
114 | simple_conv.conv_val_ptr = const_cast<char *>("DEF" ); |
115 | |
116 | LIBC_NAMESPACE::printf_core::convert(&writer, simple_conv); |
117 | |
118 | wb.buff[wb.buff_cur] = '\0'; |
119 | |
120 | ASSERT_STREQ(str, "DEF" ); |
121 | ASSERT_EQ(writer.get_chars_written(), 3); |
122 | } |
123 | |
124 | TEST_F(LlvmLibcPrintfConverterTest, StringConversionPrecisionHigh) { |
125 | LIBC_NAMESPACE::printf_core::FormatSection high_precision_conv; |
126 | high_precision_conv.has_conv = true; |
127 | high_precision_conv.raw_string = "%4s" ; |
128 | high_precision_conv.conv_name = 's'; |
129 | high_precision_conv.precision = 4; |
130 | high_precision_conv.conv_val_ptr = const_cast<char *>("456" ); |
131 | LIBC_NAMESPACE::printf_core::convert(&writer, high_precision_conv); |
132 | |
133 | wb.buff[wb.buff_cur] = '\0'; |
134 | |
135 | ASSERT_STREQ(str, "456" ); |
136 | ASSERT_EQ(writer.get_chars_written(), 3); |
137 | } |
138 | |
139 | TEST_F(LlvmLibcPrintfConverterTest, StringConversionPrecisionLow) { |
140 | LIBC_NAMESPACE::printf_core::FormatSection low_precision_conv; |
141 | low_precision_conv.has_conv = true; |
142 | low_precision_conv.raw_string = "%.2s" ; |
143 | low_precision_conv.conv_name = 's'; |
144 | low_precision_conv.precision = 2; |
145 | low_precision_conv.conv_val_ptr = const_cast<char *>("xyz" ); |
146 | LIBC_NAMESPACE::printf_core::convert(&writer, low_precision_conv); |
147 | |
148 | wb.buff[wb.buff_cur] = '\0'; |
149 | |
150 | ASSERT_STREQ(str, "xy" ); |
151 | ASSERT_EQ(writer.get_chars_written(), 2); |
152 | } |
153 | |
154 | TEST_F(LlvmLibcPrintfConverterTest, StringConversionRightJustified) { |
155 | LIBC_NAMESPACE::printf_core::FormatSection right_justified_conv; |
156 | right_justified_conv.has_conv = true; |
157 | right_justified_conv.raw_string = "%4s" ; |
158 | right_justified_conv.conv_name = 's'; |
159 | right_justified_conv.min_width = 4; |
160 | right_justified_conv.conv_val_ptr = const_cast<char *>("789" ); |
161 | LIBC_NAMESPACE::printf_core::convert(&writer, right_justified_conv); |
162 | |
163 | wb.buff[wb.buff_cur] = '\0'; |
164 | |
165 | ASSERT_STREQ(str, " 789" ); |
166 | ASSERT_EQ(writer.get_chars_written(), 4); |
167 | } |
168 | |
169 | TEST_F(LlvmLibcPrintfConverterTest, StringConversionLeftJustified) { |
170 | LIBC_NAMESPACE::printf_core::FormatSection left_justified_conv; |
171 | left_justified_conv.has_conv = true; |
172 | left_justified_conv.raw_string = "%-4s" ; |
173 | left_justified_conv.conv_name = 's'; |
174 | left_justified_conv.flags = |
175 | LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED; |
176 | left_justified_conv.min_width = 4; |
177 | left_justified_conv.conv_val_ptr = const_cast<char *>("ghi" ); |
178 | LIBC_NAMESPACE::printf_core::convert(&writer, left_justified_conv); |
179 | |
180 | wb.buff[wb.buff_cur] = '\0'; |
181 | |
182 | ASSERT_STREQ(str, "ghi " ); |
183 | ASSERT_EQ(writer.get_chars_written(), 4); |
184 | } |
185 | |
186 | TEST_F(LlvmLibcPrintfConverterTest, IntConversionSimple) { |
187 | LIBC_NAMESPACE::printf_core::FormatSection section; |
188 | section.has_conv = true; |
189 | section.raw_string = "%d" ; |
190 | section.conv_name = 'd'; |
191 | section.conv_val_raw = 12345; |
192 | LIBC_NAMESPACE::printf_core::convert(&writer, section); |
193 | |
194 | wb.buff[wb.buff_cur] = '\0'; |
195 | |
196 | ASSERT_STREQ(str, "12345" ); |
197 | ASSERT_EQ(writer.get_chars_written(), 5); |
198 | } |
199 | |
200 | TEST_F(LlvmLibcPrintfConverterTest, HexConversion) { |
201 | LIBC_NAMESPACE::printf_core::FormatSection section; |
202 | section.has_conv = true; |
203 | section.raw_string = "%#018x" ; |
204 | section.conv_name = 'x'; |
205 | section.flags = static_cast<LIBC_NAMESPACE::printf_core::FormatFlags>( |
206 | LIBC_NAMESPACE::printf_core::FormatFlags::ALTERNATE_FORM | |
207 | LIBC_NAMESPACE::printf_core::FormatFlags::LEADING_ZEROES); |
208 | section.min_width = 18; |
209 | section.conv_val_raw = 0x123456ab; |
210 | LIBC_NAMESPACE::printf_core::convert(&writer, section); |
211 | |
212 | wb.buff[wb.buff_cur] = '\0'; |
213 | ASSERT_STREQ(str, "0x00000000123456ab" ); |
214 | ASSERT_EQ(writer.get_chars_written(), 18); |
215 | } |
216 | |
217 | TEST_F(LlvmLibcPrintfConverterTest, BinaryConversion) { |
218 | LIBC_NAMESPACE::printf_core::FormatSection section; |
219 | section.has_conv = true; |
220 | section.raw_string = "%b" ; |
221 | section.conv_name = 'b'; |
222 | section.conv_val_raw = 42; |
223 | LIBC_NAMESPACE::printf_core::convert(&writer, section); |
224 | |
225 | wb.buff[wb.buff_cur] = '\0'; |
226 | |
227 | ASSERT_STREQ(str, "101010" ); |
228 | ASSERT_EQ(writer.get_chars_written(), 6); |
229 | } |
230 | |
231 | TEST_F(LlvmLibcPrintfConverterTest, PointerConversion) { |
232 | |
233 | LIBC_NAMESPACE::printf_core::FormatSection section; |
234 | section.has_conv = true; |
235 | section.raw_string = "%p" ; |
236 | section.conv_name = 'p'; |
237 | section.conv_val_ptr = (void *)(0x123456ab); |
238 | LIBC_NAMESPACE::printf_core::convert(&writer, section); |
239 | |
240 | wb.buff[wb.buff_cur] = '\0'; |
241 | ASSERT_STREQ(str, "0x123456ab" ); |
242 | ASSERT_EQ(writer.get_chars_written(), 10); |
243 | } |
244 | |
245 | TEST_F(LlvmLibcPrintfConverterTest, OctConversion) { |
246 | |
247 | LIBC_NAMESPACE::printf_core::FormatSection section; |
248 | section.has_conv = true; |
249 | section.raw_string = "%o" ; |
250 | section.conv_name = 'o'; |
251 | section.conv_val_raw = 01234; |
252 | LIBC_NAMESPACE::printf_core::convert(&writer, section); |
253 | |
254 | wb.buff[wb.buff_cur] = '\0'; |
255 | ASSERT_STREQ(str, "1234" ); |
256 | ASSERT_EQ(writer.get_chars_written(), 4); |
257 | } |
258 | |