UNIXworkcode

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 }