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), ©_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), ©_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), ©_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, ©_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, ©_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