|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
3 * |
|
4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 * POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #include "cx/printf.h" |
|
30 #include "cx/buffer.h" |
|
31 |
|
32 #include <gtest/gtest.h> |
|
33 #include "util_allocator.h" |
|
34 |
|
35 class PrintfFixture : public ::testing::Test { |
|
36 protected: |
|
37 std::string buf; |
|
38 CxTestingAllocator alloc; |
|
39 |
|
40 void TearDown() override { |
|
41 buf.clear(); |
|
42 ASSERT_TRUE(alloc.verify()); |
|
43 } |
|
44 |
|
45 static size_t write_func( |
|
46 void const *src, |
|
47 size_t esize, |
|
48 size_t ecount, |
|
49 void *target |
|
50 ) { |
|
51 auto str = reinterpret_cast<char const *>(src); |
|
52 auto buf = reinterpret_cast<std::string *>(target); |
|
53 EXPECT_EQ(esize, 1); |
|
54 EXPECT_EQ(strlen(str), ecount); |
|
55 *buf = str; |
|
56 return ecount; |
|
57 } |
|
58 }; |
|
59 |
|
60 |
|
61 TEST_F(PrintfFixture, BPrintf) { |
|
62 CxBuffer buf; |
|
63 cxBufferInit(&buf, nullptr, 64, &alloc, 0); |
|
64 |
|
65 auto r = cx_bprintf(&buf, "This %s aged %u years in a %2XSK.", "Test", 10, 0xca); |
|
66 EXPECT_EQ(r, 34); |
|
67 EXPECT_EQ(buf.size, 34); |
|
68 buf.space[r] = '\0'; |
|
69 EXPECT_STREQ(buf.space, "This Test aged 10 years in a CASK."); |
|
70 |
|
71 cxBufferDestroy(&buf); |
|
72 } |
|
73 |
|
74 TEST_F(PrintfFixture, FPrintf) { |
|
75 auto h = "Hello"; |
|
76 size_t r; |
|
77 |
|
78 r = cx_fprintf(&buf, PrintfFixture::write_func, "teststring"); |
|
79 EXPECT_EQ(r, 10); |
|
80 EXPECT_EQ(buf, "teststring"); |
|
81 |
|
82 r = cx_fprintf(&buf, PrintfFixture::write_func, "[%10s]", h); |
|
83 EXPECT_EQ(r, 12); |
|
84 EXPECT_EQ(buf, "[ Hello]"); |
|
85 |
|
86 r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10s]", h); |
|
87 EXPECT_EQ(r, 12); |
|
88 EXPECT_EQ(buf, "[Hello ]"); |
|
89 |
|
90 r = cx_fprintf(&buf, PrintfFixture::write_func, "[%*s]", 10, h); |
|
91 EXPECT_EQ(r, 12); |
|
92 EXPECT_EQ(buf, "[ Hello]"); |
|
93 |
|
94 r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10.*s]", 4, h); |
|
95 EXPECT_EQ(r, 12); |
|
96 EXPECT_EQ(buf, "[Hell ]"); |
|
97 |
|
98 r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-*.*s]", 10, 4, h); |
|
99 EXPECT_EQ(r, 12); |
|
100 EXPECT_EQ(buf, "[Hell ]"); |
|
101 |
|
102 r = cx_fprintf(&buf, PrintfFixture::write_func, "%c", 'A'); |
|
103 EXPECT_EQ(r, 1); |
|
104 EXPECT_EQ(buf, "A"); |
|
105 |
|
106 r = cx_fprintf(&buf, PrintfFixture::write_func, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); |
|
107 EXPECT_EQ(r, 19); |
|
108 EXPECT_EQ(buf, "1 2 000003 0 +4 -4"); |
|
109 |
|
110 r = cx_fprintf(&buf, PrintfFixture::write_func, "%x %x %X %#x", 5, 10, 10, 6); |
|
111 EXPECT_EQ(r, 9); |
|
112 EXPECT_EQ(buf, "5 a A 0x6"); |
|
113 |
|
114 r = cx_fprintf(&buf, PrintfFixture::write_func, "%o %#o %#o", 10, 10, 4); |
|
115 EXPECT_EQ(r, 9); |
|
116 EXPECT_EQ(buf, "12 012 04"); |
|
117 |
|
118 r = cx_fprintf(&buf, PrintfFixture::write_func, "%f %.0f %.32f", 1.5, 1.5, 1.3); |
|
119 EXPECT_EQ(r, 45); |
|
120 EXPECT_EQ(buf, "1.500000 2 1.30000000000000004440892098500626"); |
|
121 |
|
122 r = cx_fprintf(&buf, PrintfFixture::write_func, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); |
|
123 EXPECT_EQ(r, 16); |
|
124 EXPECT_EQ(buf, "01.50 1.50 1.50"); |
|
125 |
|
126 r = cx_fprintf(&buf, PrintfFixture::write_func, "%E %e", 1.5, 1.5); |
|
127 EXPECT_EQ(r, 25); |
|
128 EXPECT_EQ(buf, "1.500000E+00 1.500000e+00"); |
|
129 |
|
130 r = cx_fprintf(&buf, PrintfFixture::write_func, "%a %A", 1.5, 1.5); |
|
131 EXPECT_EQ(r, 17); |
|
132 EXPECT_EQ(buf, "0x1.8p+0 0X1.8P+0"); |
|
133 |
|
134 r = cx_fprintf(&buf, PrintfFixture::write_func, "0/0=%g 1/0=%g", 0.0 / 0.0, 1.0 / 0.0); |
|
135 EXPECT_EQ(r, 16); |
|
136 EXPECT_EQ(buf, "0/0=-nan 1/0=inf"); |
|
137 |
|
138 r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", 5, 'x'); |
|
139 EXPECT_EQ(r, 7); |
|
140 EXPECT_EQ(buf, "' x'"); |
|
141 |
|
142 r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", -5, 'x'); |
|
143 EXPECT_EQ(r, 7); |
|
144 EXPECT_EQ(buf, "'x '"); |
|
145 } |
|
146 |
|
147 TEST_F(PrintfFixture, BPrintfLargeString) { |
|
148 CxBuffer buf; |
|
149 cxBufferInit(&buf, nullptr, 64, &alloc, CX_BUFFER_AUTO_EXTEND); |
|
150 |
|
151 auto aaa = std::string(512, 'a'); |
|
152 auto bbb = std::string(512, 'b'); |
|
153 |
|
154 auto r = cx_bprintf(&buf, "After %s comes %s.", aaa.data(), bbb.data()); |
|
155 EXPECT_EQ(r, 1038); |
|
156 EXPECT_EQ(buf.size, 1038); |
|
157 cxBufferPut(&buf, 0); |
|
158 EXPECT_EQ(buf.space, std::string("After ") + aaa + " comes " + bbb + "."); |
|
159 |
|
160 cxBufferDestroy(&buf); |
|
161 } |
|
162 |
|
163 TEST_F(PrintfFixture, BPrintfNoCap) { |
|
164 CxBuffer buf; |
|
165 char space[20]; |
|
166 memset(space, 'a', 20); |
|
167 cxBufferInit(&buf, space, 16, &alloc, 0); |
|
168 |
|
169 auto r = cx_bprintf(&buf, "Hello %s with more than %d chars.", "string", 16); |
|
170 EXPECT_EQ(r, 16); |
|
171 EXPECT_EQ(buf.size, 16); |
|
172 EXPECT_EQ(0, memcmp(space, "Hello string witaaaa", 20)); |
|
173 |
|
174 cxBufferDestroy(&buf); |
|
175 } |
|
176 |
|
177 TEST_F(PrintfFixture, SPrintf) { |
|
178 auto h = "Hello"; |
|
179 |
|
180 std::vector<char *> fl; |
|
181 cxmutstr r; |
|
182 |
|
183 r = cx_asprintf_a(&alloc, "teststring"); |
|
184 EXPECT_EQ(r.length, 10); |
|
185 EXPECT_STREQ(r.ptr, "teststring"); |
|
186 fl.push_back(r.ptr); |
|
187 |
|
188 r = cx_asprintf_a(&alloc, "[%10s]", h); |
|
189 EXPECT_EQ(r.length, 12); |
|
190 EXPECT_STREQ(r.ptr, "[ Hello]"); |
|
191 fl.push_back(r.ptr); |
|
192 |
|
193 r = cx_asprintf_a(&alloc, "[%-10s]", h); |
|
194 EXPECT_EQ(r.length, 12); |
|
195 EXPECT_STREQ(r.ptr, "[Hello ]"); |
|
196 fl.push_back(r.ptr); |
|
197 |
|
198 r = cx_asprintf_a(&alloc, "[%*s]", 10, h); |
|
199 EXPECT_EQ(r.length, 12); |
|
200 EXPECT_STREQ(r.ptr, "[ Hello]"); |
|
201 fl.push_back(r.ptr); |
|
202 |
|
203 r = cx_asprintf_a(&alloc, "[%-10.*s]", 4, h); |
|
204 EXPECT_EQ(r.length, 12); |
|
205 EXPECT_STREQ(r.ptr, "[Hell ]"); |
|
206 fl.push_back(r.ptr); |
|
207 |
|
208 r = cx_asprintf_a(&alloc, "[%-*.*s]", 10, 4, h); |
|
209 EXPECT_EQ(r.length, 12); |
|
210 EXPECT_STREQ(r.ptr, "[Hell ]"); |
|
211 fl.push_back(r.ptr); |
|
212 |
|
213 r = cx_asprintf_a(&alloc, "%c", 'A'); |
|
214 EXPECT_EQ(r.length, 1); |
|
215 EXPECT_STREQ(r.ptr, "A"); |
|
216 fl.push_back(r.ptr); |
|
217 |
|
218 r = cx_asprintf_a(&alloc, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); |
|
219 EXPECT_EQ(r.length, 19); |
|
220 EXPECT_STREQ(r.ptr, "1 2 000003 0 +4 -4"); |
|
221 fl.push_back(r.ptr); |
|
222 |
|
223 r = cx_asprintf_a(&alloc, "%x %x %X %#x", 5, 10, 10, 6); |
|
224 EXPECT_EQ(r.length, 9); |
|
225 EXPECT_STREQ(r.ptr, "5 a A 0x6"); |
|
226 fl.push_back(r.ptr); |
|
227 |
|
228 r = cx_asprintf_a(&alloc, "%o %#o %#o", 10, 10, 4); |
|
229 EXPECT_EQ(r.length, 9); |
|
230 EXPECT_STREQ(r.ptr, "12 012 04"); |
|
231 fl.push_back(r.ptr); |
|
232 |
|
233 r = cx_asprintf_a(&alloc, "%f %.0f %.32f", 1.5, 1.5, 1.3); |
|
234 EXPECT_EQ(r.length, 45); |
|
235 EXPECT_STREQ(r.ptr, "1.500000 2 1.30000000000000004440892098500626"); |
|
236 fl.push_back(r.ptr); |
|
237 |
|
238 r = cx_asprintf_a(&alloc, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); |
|
239 EXPECT_EQ(r.length, 16); |
|
240 EXPECT_STREQ(r.ptr, "01.50 1.50 1.50"); |
|
241 fl.push_back(r.ptr); |
|
242 |
|
243 r = cx_asprintf_a(&alloc, "%E %e", 1.5, 1.5); |
|
244 EXPECT_EQ(r.length, 25); |
|
245 EXPECT_STREQ(r.ptr, "1.500000E+00 1.500000e+00"); |
|
246 fl.push_back(r.ptr); |
|
247 |
|
248 r = cx_asprintf_a(&alloc, "%a %A", 1.5, 1.5); |
|
249 EXPECT_EQ(r.length, 17); |
|
250 EXPECT_STREQ(r.ptr, "0x1.8p+0 0X1.8P+0"); |
|
251 fl.push_back(r.ptr); |
|
252 |
|
253 r = cx_asprintf_a(&alloc, "0/0=%g 1/0=%g", 0.0 / 0.0, 1.0 / 0.0); |
|
254 EXPECT_EQ(r.length, 16); |
|
255 EXPECT_STREQ(r.ptr, "0/0=-nan 1/0=inf"); |
|
256 fl.push_back(r.ptr); |
|
257 |
|
258 r = cx_asprintf_a(&alloc, "'%*c'", 5, 'x'); |
|
259 EXPECT_EQ(r.length, 7); |
|
260 EXPECT_STREQ(r.ptr, "' x'"); |
|
261 fl.push_back(r.ptr); |
|
262 |
|
263 r = cx_asprintf_a(&alloc, "'%*c'", -5, 'x'); |
|
264 EXPECT_EQ(r.length, 7); |
|
265 EXPECT_STREQ(r.ptr, "'x '"); |
|
266 fl.push_back(r.ptr); |
|
267 |
|
268 for (auto c: fl) { |
|
269 auto s = cx_mutstrn(c, 0); |
|
270 cx_strfree_a(&alloc, &s); |
|
271 } |
|
272 } |
|
273 |
|
274 TEST_F(PrintfFixture, SPrintfLargeString) { |
|
275 auto aaa = std::string(512, 'a'); |
|
276 auto bbb = std::string(512, 'b'); |
|
277 |
|
278 auto r = cx_asprintf_a(&alloc, "After %s comes %s.", aaa.data(), bbb.data()); |
|
279 EXPECT_EQ(r.length, 1038); |
|
280 EXPECT_EQ(r.ptr, std::string("After ") + aaa + " comes " + bbb + "."); |
|
281 EXPECT_EQ(r.ptr[1038], '\0'); |
|
282 |
|
283 cx_strfree_a(&alloc, &r); |
|
284 } |