xref: /aosp_15_r20/external/llvm-libc/test/src/stdio/printf_core/writer_test.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Unittests for the printf String Writer ----------------------------===//
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/printf_core/writer.h"
11 
12 #include "src/string/memory_utils/inline_memcpy.h"
13 
14 #include "test/UnitTest/Test.h"
15 
16 using LIBC_NAMESPACE::cpp::string_view;
17 using LIBC_NAMESPACE::printf_core::WriteBuffer;
18 using LIBC_NAMESPACE::printf_core::Writer;
19 
TEST(LlvmLibcPrintfWriterTest,Constructor)20 TEST(LlvmLibcPrintfWriterTest, Constructor) {
21   char str[10];
22   WriteBuffer wb(str, sizeof(str) - 1);
23   Writer writer(&wb);
24   (void)writer;
25 }
26 
TEST(LlvmLibcPrintfWriterTest,Write)27 TEST(LlvmLibcPrintfWriterTest, Write) {
28   char str[4] = {'D', 'E', 'F', 'G'};
29   WriteBuffer wb(str, sizeof(str) - 1);
30   Writer writer(&wb);
31   writer.write({"abc", 3});
32 
33   EXPECT_EQ(str[3], 'G');
34 
35   // The string must be null terminated manually since the writer cannot tell
36   // when it's done.
37   wb.buff[wb.buff_cur] = '\0';
38 
39   ASSERT_STREQ("abc", str);
40   ASSERT_EQ(writer.get_chars_written(), 3);
41 }
42 
TEST(LlvmLibcPrintfWriterTest,WriteMultipleTimes)43 TEST(LlvmLibcPrintfWriterTest, WriteMultipleTimes) {
44   char str[10];
45   WriteBuffer wb(str, sizeof(str) - 1);
46   Writer writer(&wb);
47   writer.write({"abc", 3});
48   writer.write({"DEF", 3});
49   writer.write({"1234", 3});
50 
51   wb.buff[wb.buff_cur] = '\0';
52 
53   ASSERT_STREQ("abcDEF123", str);
54   ASSERT_EQ(writer.get_chars_written(), 9);
55 }
56 
TEST(LlvmLibcPrintfWriterTest,WriteChars)57 TEST(LlvmLibcPrintfWriterTest, WriteChars) {
58   char str[4] = {'D', 'E', 'F', 'G'};
59   WriteBuffer wb(str, sizeof(str) - 1);
60   Writer writer(&wb);
61   writer.write('a', 3);
62 
63   EXPECT_EQ(str[3], 'G');
64   wb.buff[wb.buff_cur] = '\0';
65 
66   ASSERT_STREQ("aaa", str);
67   ASSERT_EQ(writer.get_chars_written(), 3);
68 }
69 
TEST(LlvmLibcPrintfWriterTest,WriteCharsMultipleTimes)70 TEST(LlvmLibcPrintfWriterTest, WriteCharsMultipleTimes) {
71   char str[10];
72   WriteBuffer wb(str, sizeof(str) - 1);
73   Writer writer(&wb);
74   writer.write('a', 3);
75   writer.write('D', 3);
76   writer.write('1', 3);
77 
78   wb.buff[wb.buff_cur] = '\0';
79 
80   ASSERT_STREQ("aaaDDD111", str);
81   ASSERT_EQ(writer.get_chars_written(), 9);
82 }
83 
TEST(LlvmLibcPrintfWriterTest,WriteManyChars)84 TEST(LlvmLibcPrintfWriterTest, WriteManyChars) {
85   char str[100];
86   WriteBuffer wb(str, sizeof(str) - 1);
87   Writer writer(&wb);
88   writer.write('Z', 99);
89 
90   wb.buff[wb.buff_cur] = '\0';
91 
92   ASSERT_STREQ("ZZZZZZZZZZ"
93                "ZZZZZZZZZZ"
94                "ZZZZZZZZZZ"
95                "ZZZZZZZZZZ"
96                "ZZZZZZZZZZ"
97                "ZZZZZZZZZZ"
98                "ZZZZZZZZZZ"
99                "ZZZZZZZZZZ"
100                "ZZZZZZZZZZ"
101                "ZZZZZZZZZ",
102                str);
103   ASSERT_EQ(writer.get_chars_written(), 99);
104 }
105 
TEST(LlvmLibcPrintfWriterTest,MixedWrites)106 TEST(LlvmLibcPrintfWriterTest, MixedWrites) {
107   char str[13];
108   WriteBuffer wb(str, sizeof(str) - 1);
109   Writer writer(&wb);
110   writer.write('a', 3);
111   writer.write({"DEF", 3});
112   writer.write('1', 3);
113   writer.write({"456", 3});
114 
115   wb.buff[wb.buff_cur] = '\0';
116 
117   ASSERT_STREQ("aaaDEF111456", str);
118   ASSERT_EQ(writer.get_chars_written(), 12);
119 }
120 
TEST(LlvmLibcPrintfWriterTest,WriteWithMaxLength)121 TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLength) {
122   char str[11];
123   WriteBuffer wb(str, sizeof(str) - 1);
124   Writer writer(&wb);
125   writer.write({"abcDEF123456", 12});
126 
127   wb.buff[wb.buff_cur] = '\0';
128 
129   ASSERT_STREQ("abcDEF1234", str);
130   ASSERT_EQ(writer.get_chars_written(), 12);
131 }
132 
TEST(LlvmLibcPrintfWriterTest,WriteCharsWithMaxLength)133 TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLength) {
134   char str[11];
135   WriteBuffer wb(str, sizeof(str) - 1);
136   Writer writer(&wb);
137   writer.write('1', 15);
138 
139   wb.buff[wb.buff_cur] = '\0';
140 
141   ASSERT_STREQ("1111111111", str);
142   ASSERT_EQ(writer.get_chars_written(), 15);
143 }
144 
TEST(LlvmLibcPrintfWriterTest,MixedWriteWithMaxLength)145 TEST(LlvmLibcPrintfWriterTest, MixedWriteWithMaxLength) {
146   char str[11];
147   WriteBuffer wb(str, sizeof(str) - 1);
148 
149   Writer writer(&wb);
150   writer.write('a', 3);
151   writer.write({"DEF", 3});
152   writer.write('1', 3);
153   writer.write({"456", 3});
154 
155   wb.buff[wb.buff_cur] = '\0';
156 
157   ASSERT_STREQ("aaaDEF1114", str);
158   ASSERT_EQ(writer.get_chars_written(), 12);
159 }
160 
TEST(LlvmLibcPrintfWriterTest,StringWithMaxLengthOne)161 TEST(LlvmLibcPrintfWriterTest, StringWithMaxLengthOne) {
162   char str[1];
163   // This is because the max length should be at most 1 less than the size of
164   // the buffer it's writing to.
165   WriteBuffer wb(str, 0);
166 
167   Writer writer(&wb);
168   writer.write('a', 3);
169   writer.write({"DEF", 3});
170   writer.write('1', 3);
171   writer.write({"456", 3});
172 
173   wb.buff[wb.buff_cur] = '\0';
174 
175   ASSERT_STREQ("", str);
176   ASSERT_EQ(writer.get_chars_written(), 12);
177 }
178 
TEST(LlvmLibcPrintfWriterTest,NullStringWithZeroMaxLength)179 TEST(LlvmLibcPrintfWriterTest, NullStringWithZeroMaxLength) {
180   WriteBuffer wb(nullptr, 0);
181 
182   Writer writer(&wb);
183   writer.write('a', 3);
184   writer.write({"DEF", 3});
185   writer.write('1', 3);
186   writer.write({"456", 3});
187 
188   ASSERT_EQ(writer.get_chars_written(), 12);
189 }
190 
191 struct OutBuff {
192   char *out_str;
193   size_t cur_pos = 0;
194 };
195 
copy_to_out(string_view new_str,void * raw_out_buff)196 int copy_to_out(string_view new_str, void *raw_out_buff) {
197   if (new_str.size() == 0) {
198     return 0;
199   }
200 
201   OutBuff *out_buff = reinterpret_cast<OutBuff *>(raw_out_buff);
202 
203   LIBC_NAMESPACE::inline_memcpy(out_buff->out_str + out_buff->cur_pos,
204                                 new_str.data(), new_str.size());
205 
206   out_buff->cur_pos += new_str.size();
207   return 0;
208 }
209 
TEST(LlvmLibcPrintfWriterTest,WriteWithMaxLengthWithCallback)210 TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLengthWithCallback) {
211   char str[16];
212 
213   OutBuff out_buff = {str, 0};
214 
215   char wb_buff[8];
216   WriteBuffer wb(wb_buff, sizeof(wb_buff), &copy_to_out,
217                  reinterpret_cast<void *>(&out_buff));
218   Writer writer(&wb);
219   writer.write({"abcDEF123456", 12});
220 
221   // Flush the buffer
222   wb.overflow_write("");
223   str[out_buff.cur_pos] = '\0';
224 
225   ASSERT_STREQ("abcDEF123456", str);
226   ASSERT_EQ(writer.get_chars_written(), 12);
227 }
228 
TEST(LlvmLibcPrintfWriterTest,WriteCharsWithMaxLengthWithCallback)229 TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLengthWithCallback) {
230   char str[16];
231 
232   OutBuff out_buff = {str, 0};
233 
234   char wb_buff[8];
235   WriteBuffer wb(wb_buff, sizeof(wb_buff), &copy_to_out,
236                  reinterpret_cast<void *>(&out_buff));
237   Writer writer(&wb);
238   writer.write('1', 15);
239 
240   // Flush the buffer
241   wb.overflow_write("");
242   str[out_buff.cur_pos] = '\0';
243 
244   ASSERT_STREQ("111111111111111", str);
245   ASSERT_EQ(writer.get_chars_written(), 15);
246 }
247 
TEST(LlvmLibcPrintfWriterTest,MixedWriteWithMaxLengthWithCallback)248 TEST(LlvmLibcPrintfWriterTest, MixedWriteWithMaxLengthWithCallback) {
249   char str[16];
250 
251   OutBuff out_buff = {str, 0};
252 
253   char wb_buff[8];
254   WriteBuffer wb(wb_buff, sizeof(wb_buff), &copy_to_out,
255                  reinterpret_cast<void *>(&out_buff));
256   Writer writer(&wb);
257   writer.write('a', 3);
258   writer.write({"DEF", 3});
259   writer.write('1', 3);
260   writer.write({"456", 3});
261 
262   // Flush the buffer
263   wb.overflow_write("");
264   str[out_buff.cur_pos] = '\0';
265 
266   ASSERT_STREQ("aaaDEF111456", str);
267   ASSERT_EQ(writer.get_chars_written(), 12);
268 }
269 
TEST(LlvmLibcPrintfWriterTest,ZeroLengthBufferWithCallback)270 TEST(LlvmLibcPrintfWriterTest, ZeroLengthBufferWithCallback) {
271   char str[16];
272 
273   OutBuff out_buff = {str, 0};
274 
275   char wb_buff[1];
276   WriteBuffer wb(wb_buff, 0, &copy_to_out, reinterpret_cast<void *>(&out_buff));
277 
278   Writer writer(&wb);
279   writer.write('a', 3);
280   writer.write({"DEF", 3});
281   writer.write('1', 3);
282   writer.write({"456", 3});
283 
284   // Flush the buffer
285   wb.overflow_write("");
286   str[out_buff.cur_pos] = '\0';
287 
288   ASSERT_STREQ("aaaDEF111456", str);
289   ASSERT_EQ(writer.get_chars_written(), 12);
290 }
291 
TEST(LlvmLibcPrintfWriterTest,NullStringWithZeroMaxLengthWithCallback)292 TEST(LlvmLibcPrintfWriterTest, NullStringWithZeroMaxLengthWithCallback) {
293   char str[16];
294 
295   OutBuff out_buff = {str, 0};
296 
297   WriteBuffer wb(nullptr, 0, &copy_to_out, reinterpret_cast<void *>(&out_buff));
298 
299   Writer writer(&wb);
300   writer.write('a', 3);
301   writer.write({"DEF", 3});
302   writer.write('1', 3);
303   writer.write({"456", 3});
304 
305   wb.overflow_write("");
306   str[out_buff.cur_pos] = '\0';
307 
308   ASSERT_EQ(writer.get_chars_written(), 12);
309   ASSERT_STREQ("aaaDEF111456", str);
310 }
311