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
15class LlvmLibcPrintfConverterTest : public LIBC_NAMESPACE::testing::Test {
16protected:
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
31TEST_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
44TEST_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
58TEST_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
76TEST_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
91TEST_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
108TEST_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
124TEST_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
139TEST_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
154TEST_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
169TEST_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
186TEST_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
200TEST_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
217TEST_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
231TEST_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
245TEST_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

source code of libc/test/src/stdio/printf_core/converter_test.cpp