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

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