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/stdio/printf_core/string_writer.h"
10 #include "src/stdio/printf_core/writer.h"
11 
12 #include "utils/UnitTest/Test.h"
13 
TEST(LlvmLibcPrintfStringWriterTest,Constructor)14 TEST(LlvmLibcPrintfStringWriterTest, Constructor) {
15   char str[10];
16   __llvm_libc::printf_core::StringWriter str_writer(str);
17   __llvm_libc::printf_core::Writer writer(
18       reinterpret_cast<void *>(&str_writer),
19       __llvm_libc::printf_core::write_to_string);
20 }
21 
TEST(LlvmLibcPrintfStringWriterTest,Write)22 TEST(LlvmLibcPrintfStringWriterTest, Write) {
23   char str[4] = {'D', 'E', 'F', 'G'};
24   __llvm_libc::printf_core::StringWriter str_writer(str);
25   __llvm_libc::printf_core::Writer writer(
26       reinterpret_cast<void *>(&str_writer),
27       __llvm_libc::printf_core::write_to_string);
28   writer.write("abc", 3);
29 
30   EXPECT_EQ(str[3], 'G');
31   // This null terminates the string. The writer has no indication when the
32   // string is done, so it relies on the user to tell it when to null terminate
33   // the string. Importantly, it can't tell the difference between an intended
34   // max length of 0 (write nothing) or 1 (write just a null byte), and so it
35   // relies on the caller to do that bounds check.
36   str_writer.terminate();
37 
38   ASSERT_STREQ("abc", str);
39   ASSERT_EQ(writer.get_chars_written(), 3);
40 }
41 
TEST(LlvmLibcPrintfStringWriterTest,WriteMultipleTimes)42 TEST(LlvmLibcPrintfStringWriterTest, WriteMultipleTimes) {
43   char str[10];
44   __llvm_libc::printf_core::StringWriter str_writer(str);
45   __llvm_libc::printf_core::Writer writer(
46       reinterpret_cast<void *>(&str_writer),
47       __llvm_libc::printf_core::write_to_string);
48   writer.write("abc", 3);
49   writer.write("DEF", 3);
50   writer.write("1234", 3);
51 
52   str_writer.terminate();
53 
54   ASSERT_STREQ("abcDEF123", str);
55   ASSERT_EQ(writer.get_chars_written(), 9);
56 }
57 
TEST(LlvmLibcPrintfStringWriterTest,WriteChars)58 TEST(LlvmLibcPrintfStringWriterTest, WriteChars) {
59   char str[4] = {'D', 'E', 'F', 'G'};
60   __llvm_libc::printf_core::StringWriter str_writer(str);
61   __llvm_libc::printf_core::Writer writer(
62       reinterpret_cast<void *>(&str_writer),
63       __llvm_libc::printf_core::write_to_string);
64   writer.write_chars('a', 3);
65 
66   EXPECT_EQ(str[3], 'G');
67   str_writer.terminate();
68 
69   ASSERT_STREQ("aaa", str);
70   ASSERT_EQ(writer.get_chars_written(), 3);
71 }
72 
TEST(LlvmLibcPrintfStringWriterTest,WriteCharsMultipleTimes)73 TEST(LlvmLibcPrintfStringWriterTest, WriteCharsMultipleTimes) {
74   char str[10];
75   __llvm_libc::printf_core::StringWriter str_writer(str);
76   __llvm_libc::printf_core::Writer writer(
77       reinterpret_cast<void *>(&str_writer),
78       __llvm_libc::printf_core::write_to_string);
79   writer.write_chars('a', 3);
80   writer.write_chars('D', 3);
81   writer.write_chars('1', 3);
82 
83   str_writer.terminate();
84 
85   ASSERT_STREQ("aaaDDD111", str);
86   ASSERT_EQ(writer.get_chars_written(), 9);
87 }
88 
TEST(LlvmLibcPrintfStringWriterTest,WriteManyChars)89 TEST(LlvmLibcPrintfStringWriterTest, WriteManyChars) {
90   char str[100];
91   __llvm_libc::printf_core::StringWriter str_writer(str);
92   __llvm_libc::printf_core::Writer writer(
93       reinterpret_cast<void *>(&str_writer),
94       __llvm_libc::printf_core::write_to_string);
95   writer.write_chars('Z', 99);
96 
97   str_writer.terminate();
98 
99   ASSERT_STREQ("ZZZZZZZZZZ"
100                "ZZZZZZZZZZ"
101                "ZZZZZZZZZZ"
102                "ZZZZZZZZZZ"
103                "ZZZZZZZZZZ"
104                "ZZZZZZZZZZ"
105                "ZZZZZZZZZZ"
106                "ZZZZZZZZZZ"
107                "ZZZZZZZZZZ"
108                "ZZZZZZZZZ",
109                str);
110   ASSERT_EQ(writer.get_chars_written(), 99);
111 }
112 
TEST(LlvmLibcPrintfStringWriterTest,MixedWrites)113 TEST(LlvmLibcPrintfStringWriterTest, MixedWrites) {
114   char str[13];
115   __llvm_libc::printf_core::StringWriter str_writer(str);
116   __llvm_libc::printf_core::Writer writer(
117       reinterpret_cast<void *>(&str_writer),
118       __llvm_libc::printf_core::write_to_string);
119   writer.write_chars('a', 3);
120   writer.write("DEF", 3);
121   writer.write_chars('1', 3);
122   writer.write("456", 3);
123 
124   str_writer.terminate();
125 
126   ASSERT_STREQ("aaaDEF111456", str);
127   ASSERT_EQ(writer.get_chars_written(), 12);
128 }
129 
TEST(LlvmLibcPrintfStringWriterTest,WriteWithMaxLength)130 TEST(LlvmLibcPrintfStringWriterTest, WriteWithMaxLength) {
131   char str[11];
132   __llvm_libc::printf_core::StringWriter str_writer(str, 10);
133   __llvm_libc::printf_core::Writer writer(
134       reinterpret_cast<void *>(&str_writer),
135       __llvm_libc::printf_core::write_to_string);
136   writer.write("abcDEF123456", 12);
137 
138   str_writer.terminate();
139 
140   ASSERT_STREQ("abcDEF1234", str);
141   ASSERT_EQ(writer.get_chars_written(), 12);
142 }
143 
TEST(LlvmLibcPrintfStringWriterTest,WriteCharsWithMaxLength)144 TEST(LlvmLibcPrintfStringWriterTest, WriteCharsWithMaxLength) {
145   char str[11];
146   __llvm_libc::printf_core::StringWriter str_writer(str, 10);
147   __llvm_libc::printf_core::Writer writer(
148       reinterpret_cast<void *>(&str_writer),
149       __llvm_libc::printf_core::write_to_string);
150 
151   writer.write_chars('1', 15);
152 
153   str_writer.terminate();
154 
155   ASSERT_STREQ("1111111111", str);
156   ASSERT_EQ(writer.get_chars_written(), 15);
157 }
158 
TEST(LlvmLibcPrintfStringWriterTest,MixedWriteWithMaxLength)159 TEST(LlvmLibcPrintfStringWriterTest, MixedWriteWithMaxLength) {
160   char str[11];
161   __llvm_libc::printf_core::StringWriter str_writer(str, 10);
162   __llvm_libc::printf_core::Writer writer(
163       reinterpret_cast<void *>(&str_writer),
164       __llvm_libc::printf_core::write_to_string);
165   writer.write_chars('a', 3);
166   writer.write("DEF", 3);
167   writer.write_chars('1', 3);
168   writer.write("456", 3);
169 
170   str_writer.terminate();
171 
172   ASSERT_STREQ("aaaDEF1114", str);
173   ASSERT_EQ(writer.get_chars_written(), 12);
174 }
175 
TEST(LlvmLibcPrintfStringWriterTest,StringWithMaxLengthOne)176 TEST(LlvmLibcPrintfStringWriterTest, StringWithMaxLengthOne) {
177   char str[1];
178   __llvm_libc::printf_core::StringWriter str_writer(str, 0);
179   __llvm_libc::printf_core::Writer writer(
180       reinterpret_cast<void *>(&str_writer),
181       __llvm_libc::printf_core::write_to_string);
182   // This is because the max length should be at most 1 less than the size of
183   // the buffer it's writing to.
184   writer.write_chars('a', 3);
185   writer.write("DEF", 3);
186   writer.write_chars('1', 3);
187   writer.write("456", 3);
188 
189   str_writer.terminate();
190 
191   ASSERT_STREQ("", str);
192   ASSERT_EQ(writer.get_chars_written(), 12);
193 }
194 
TEST(LlvmLibcPrintfStringWriterTest,NullStringWithZeroMaxLength)195 TEST(LlvmLibcPrintfStringWriterTest, NullStringWithZeroMaxLength) {
196   __llvm_libc::printf_core::StringWriter str_writer(nullptr, 0);
197   __llvm_libc::printf_core::Writer writer(
198       reinterpret_cast<void *>(&str_writer),
199       __llvm_libc::printf_core::write_to_string);
200   writer.write_chars('a', 3);
201   writer.write("DEF", 3);
202   writer.write_chars('1', 3);
203   writer.write("456", 3);
204 
205   ASSERT_EQ(writer.get_chars_written(), 12);
206 }
207