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

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