|
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, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); |
|
119 EXPECT_EQ(r, 16); |
|
120 EXPECT_EQ(buf, "01.50 1.50 1.50"); |
|
121 |
|
122 r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", 5, 'x'); |
|
123 EXPECT_EQ(r, 7); |
|
124 EXPECT_EQ(buf, "' x'"); |
|
125 |
|
126 r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", -5, 'x'); |
|
127 EXPECT_EQ(r, 7); |
|
128 EXPECT_EQ(buf, "'x '"); |
|
129 } |
|
130 |
|
131 TEST_F(PrintfFixture, BPrintfLargeString) { |
|
132 CxBuffer buf; |
|
133 cxBufferInit(&buf, nullptr, 64, &alloc, CX_BUFFER_AUTO_EXTEND); |
|
134 |
|
135 auto aaa = std::string(512, 'a'); |
|
136 auto bbb = std::string(512, 'b'); |
|
137 |
|
138 auto r = cx_bprintf(&buf, "After %s comes %s.", aaa.data(), bbb.data()); |
|
139 EXPECT_EQ(r, 1038); |
|
140 EXPECT_EQ(buf.size, 1038); |
|
141 cxBufferPut(&buf, 0); |
|
142 EXPECT_EQ(buf.space, std::string("After ") + aaa + " comes " + bbb + "."); |
|
143 |
|
144 cxBufferDestroy(&buf); |
|
145 } |
|
146 |
|
147 TEST_F(PrintfFixture, BPrintfNoCap) { |
|
148 CxBuffer buf; |
|
149 char space[20]; |
|
150 memset(space, 'a', 20); |
|
151 cxBufferInit(&buf, space, 16, &alloc, 0); |
|
152 |
|
153 auto r = cx_bprintf(&buf, "Hello %s with more than %d chars.", "string", 16); |
|
154 EXPECT_EQ(r, 16); |
|
155 EXPECT_EQ(buf.size, 16); |
|
156 EXPECT_EQ(0, memcmp(space, "Hello string witaaaa", 20)); |
|
157 |
|
158 cxBufferDestroy(&buf); |
|
159 } |
|
160 |
|
161 TEST_F(PrintfFixture, SPrintf) { |
|
162 auto h = "Hello"; |
|
163 |
|
164 std::vector<char *> fl; |
|
165 cxmutstr r; |
|
166 |
|
167 r = cx_asprintf_a(&alloc, "teststring"); |
|
168 EXPECT_EQ(r.length, 10); |
|
169 EXPECT_STREQ(r.ptr, "teststring"); |
|
170 fl.push_back(r.ptr); |
|
171 |
|
172 r = cx_asprintf_a(&alloc, "[%10s]", h); |
|
173 EXPECT_EQ(r.length, 12); |
|
174 EXPECT_STREQ(r.ptr, "[ Hello]"); |
|
175 fl.push_back(r.ptr); |
|
176 |
|
177 r = cx_asprintf_a(&alloc, "[%-10s]", h); |
|
178 EXPECT_EQ(r.length, 12); |
|
179 EXPECT_STREQ(r.ptr, "[Hello ]"); |
|
180 fl.push_back(r.ptr); |
|
181 |
|
182 r = cx_asprintf_a(&alloc, "[%*s]", 10, h); |
|
183 EXPECT_EQ(r.length, 12); |
|
184 EXPECT_STREQ(r.ptr, "[ Hello]"); |
|
185 fl.push_back(r.ptr); |
|
186 |
|
187 r = cx_asprintf_a(&alloc, "[%-10.*s]", 4, h); |
|
188 EXPECT_EQ(r.length, 12); |
|
189 EXPECT_STREQ(r.ptr, "[Hell ]"); |
|
190 fl.push_back(r.ptr); |
|
191 |
|
192 r = cx_asprintf_a(&alloc, "[%-*.*s]", 10, 4, h); |
|
193 EXPECT_EQ(r.length, 12); |
|
194 EXPECT_STREQ(r.ptr, "[Hell ]"); |
|
195 fl.push_back(r.ptr); |
|
196 |
|
197 r = cx_asprintf_a(&alloc, "%c", 'A'); |
|
198 EXPECT_EQ(r.length, 1); |
|
199 EXPECT_STREQ(r.ptr, "A"); |
|
200 fl.push_back(r.ptr); |
|
201 |
|
202 r = cx_asprintf_a(&alloc, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); |
|
203 EXPECT_EQ(r.length, 19); |
|
204 EXPECT_STREQ(r.ptr, "1 2 000003 0 +4 -4"); |
|
205 fl.push_back(r.ptr); |
|
206 |
|
207 r = cx_asprintf_a(&alloc, "%x %x %X %#x", 5, 10, 10, 6); |
|
208 EXPECT_EQ(r.length, 9); |
|
209 EXPECT_STREQ(r.ptr, "5 a A 0x6"); |
|
210 fl.push_back(r.ptr); |
|
211 |
|
212 r = cx_asprintf_a(&alloc, "%o %#o %#o", 10, 10, 4); |
|
213 EXPECT_EQ(r.length, 9); |
|
214 EXPECT_STREQ(r.ptr, "12 012 04"); |
|
215 fl.push_back(r.ptr); |
|
216 |
|
217 r = cx_asprintf_a(&alloc, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); |
|
218 EXPECT_EQ(r.length, 16); |
|
219 EXPECT_STREQ(r.ptr, "01.50 1.50 1.50"); |
|
220 fl.push_back(r.ptr); |
|
221 |
|
222 r = cx_asprintf_a(&alloc, "'%*c'", 5, 'x'); |
|
223 EXPECT_EQ(r.length, 7); |
|
224 EXPECT_STREQ(r.ptr, "' x'"); |
|
225 fl.push_back(r.ptr); |
|
226 |
|
227 r = cx_asprintf_a(&alloc, "'%*c'", -5, 'x'); |
|
228 EXPECT_EQ(r.length, 7); |
|
229 EXPECT_STREQ(r.ptr, "'x '"); |
|
230 fl.push_back(r.ptr); |
|
231 |
|
232 for (auto c: fl) { |
|
233 auto s = cx_mutstrn(c, 0); |
|
234 cx_strfree_a(&alloc, &s); |
|
235 } |
|
236 } |
|
237 |
|
238 TEST_F(PrintfFixture, SPrintfLargeString) { |
|
239 auto aaa = std::string(512, 'a'); |
|
240 auto bbb = std::string(512, 'b'); |
|
241 |
|
242 auto r = cx_asprintf_a(&alloc, "After %s comes %s.", aaa.data(), bbb.data()); |
|
243 EXPECT_EQ(r.length, 1038); |
|
244 EXPECT_EQ(r.ptr, std::string("After ") + aaa + " comes " + bbb + "."); |
|
245 EXPECT_EQ(r.ptr[1038], '\0'); |
|
246 |
|
247 cx_strfree_a(&alloc, &r); |
|
248 } |