tests/test_printf.cpp

Sun, 16 Apr 2023 21:35:08 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 16 Apr 2023 21:35:08 +0200
changeset 683
aa0d09f2d81c
parent 653
e081643aae2a
permissions
-rw-r--r--

add convenience functions for allocating a buffer on the heap

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "cx/printf.h"
#include "cx/buffer.h"

#include <gtest/gtest.h>
#include "util_allocator.h"

class PrintfFixture : public ::testing::Test {
protected:
    std::string buf;
    CxTestingAllocator alloc;

    void TearDown() override {
        buf.clear();
        ASSERT_TRUE(alloc.verify());
    }

    static size_t write_func(
            void const *src,
            size_t esize,
            size_t ecount,
            void *target
    ) {
        auto str = reinterpret_cast<char const *>(src);
        auto buf = reinterpret_cast<std::string *>(target);
        EXPECT_EQ(esize, 1);
        EXPECT_EQ(strlen(str), ecount);
        *buf = str;
        return ecount;
    }
};


TEST_F(PrintfFixture, BPrintf) {
    CxBuffer buf;
    cxBufferInit(&buf, nullptr, 64, &alloc, 0);

    auto r = cx_bprintf(&buf, "This %s aged %u years in a %2XSK.", "Test", 10, 0xca);
    EXPECT_EQ(r, 34);
    EXPECT_EQ(buf.size, 34);
    buf.space[r] = '\0';
    EXPECT_STREQ(buf.space, "This Test aged 10 years in a CASK.");

    cxBufferDestroy(&buf);
}

TEST_F(PrintfFixture, FPrintf) {
    auto h = "Hello";
    size_t r;

    r = cx_fprintf(&buf, PrintfFixture::write_func, "teststring");
    EXPECT_EQ(r, 10);
    EXPECT_EQ(buf, "teststring");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "[%10s]", h);
    EXPECT_EQ(r, 12);
    EXPECT_EQ(buf, "[     Hello]");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10s]", h);
    EXPECT_EQ(r, 12);
    EXPECT_EQ(buf, "[Hello     ]");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "[%*s]", 10, h);
    EXPECT_EQ(r, 12);
    EXPECT_EQ(buf, "[     Hello]");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10.*s]", 4, h);
    EXPECT_EQ(r, 12);
    EXPECT_EQ(buf, "[Hell      ]");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-*.*s]", 10, 4, h);
    EXPECT_EQ(r, 12);
    EXPECT_EQ(buf, "[Hell      ]");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "%c", 'A');
    EXPECT_EQ(r, 1);
    EXPECT_EQ(buf, "A");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4);
    EXPECT_EQ(r, 19);
    EXPECT_EQ(buf, "1 2 000003 0  +4 -4");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "%x %x %X %#x", 5, 10, 10, 6);
    EXPECT_EQ(r, 9);
    EXPECT_EQ(buf, "5 a A 0x6");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "%o %#o %#o", 10, 10, 4);
    EXPECT_EQ(r, 9);
    EXPECT_EQ(buf, "12 012 04");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5);
    EXPECT_EQ(r, 16);
    EXPECT_EQ(buf, "01.50 1.50  1.50");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", 5, 'x');
    EXPECT_EQ(r, 7);
    EXPECT_EQ(buf, "'    x'");

    r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", -5, 'x');
    EXPECT_EQ(r, 7);
    EXPECT_EQ(buf, "'x    '");
}

TEST_F(PrintfFixture, BPrintfLargeString) {
    CxBuffer buf;
    cxBufferInit(&buf, nullptr, 64, &alloc, CX_BUFFER_AUTO_EXTEND);

    auto aaa = std::string(512, 'a');
    auto bbb = std::string(512, 'b');

    auto r = cx_bprintf(&buf, "After %s comes %s.", aaa.data(), bbb.data());
    EXPECT_EQ(r, 1038);
    EXPECT_EQ(buf.size, 1038);
    cxBufferPut(&buf, 0);
    EXPECT_EQ(buf.space, std::string("After ") + aaa + " comes " + bbb + ".");

    cxBufferDestroy(&buf);
}

TEST_F(PrintfFixture, BPrintfNoCap) {
    CxBuffer buf;
    char space[20];
    memset(space, 'a', 20);
    cxBufferInit(&buf, space, 16, &alloc, 0);

    auto r = cx_bprintf(&buf, "Hello %s with more than %d chars.", "string", 16);
    EXPECT_EQ(r, 16);
    EXPECT_EQ(buf.size, 16);
    EXPECT_EQ(0, memcmp(space, "Hello string witaaaa", 20));

    cxBufferDestroy(&buf);
}

TEST_F(PrintfFixture, SPrintf) {
    auto h = "Hello";

    std::vector<char *> fl;
    cxmutstr r;

    r = cx_asprintf_a(&alloc, "teststring");
    EXPECT_EQ(r.length, 10);
    EXPECT_STREQ(r.ptr, "teststring");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "[%10s]", h);
    EXPECT_EQ(r.length, 12);
    EXPECT_STREQ(r.ptr, "[     Hello]");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "[%-10s]", h);
    EXPECT_EQ(r.length, 12);
    EXPECT_STREQ(r.ptr, "[Hello     ]");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "[%*s]", 10, h);
    EXPECT_EQ(r.length, 12);
    EXPECT_STREQ(r.ptr, "[     Hello]");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "[%-10.*s]", 4, h);
    EXPECT_EQ(r.length, 12);
    EXPECT_STREQ(r.ptr, "[Hell      ]");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "[%-*.*s]", 10, 4, h);
    EXPECT_EQ(r.length, 12);
    EXPECT_STREQ(r.ptr, "[Hell      ]");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "%c", 'A');
    EXPECT_EQ(r.length, 1);
    EXPECT_STREQ(r.ptr, "A");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4);
    EXPECT_EQ(r.length, 19);
    EXPECT_STREQ(r.ptr, "1 2 000003 0  +4 -4");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "%x %x %X %#x", 5, 10, 10, 6);
    EXPECT_EQ(r.length, 9);
    EXPECT_STREQ(r.ptr, "5 a A 0x6");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "%o %#o %#o", 10, 10, 4);
    EXPECT_EQ(r.length, 9);
    EXPECT_STREQ(r.ptr, "12 012 04");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5);
    EXPECT_EQ(r.length, 16);
    EXPECT_STREQ(r.ptr, "01.50 1.50  1.50");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "'%*c'", 5, 'x');
    EXPECT_EQ(r.length, 7);
    EXPECT_STREQ(r.ptr, "'    x'");
    fl.push_back(r.ptr);

    r = cx_asprintf_a(&alloc, "'%*c'", -5, 'x');
    EXPECT_EQ(r.length, 7);
    EXPECT_STREQ(r.ptr, "'x    '");
    fl.push_back(r.ptr);

    for (auto c: fl) {
        auto s = cx_mutstrn(c, 0);
        cx_strfree_a(&alloc, &s);
    }
}

TEST_F(PrintfFixture, SPrintfLargeString) {
    auto aaa = std::string(512, 'a');
    auto bbb = std::string(512, 'b');

    auto r = cx_asprintf_a(&alloc, "After %s comes %s.", aaa.data(), bbb.data());
    EXPECT_EQ(r.length, 1038);
    EXPECT_EQ(r.ptr, std::string("After ") + aaa + " comes " + bbb + ".");
    EXPECT_EQ(r.ptr[1038], '\0');

    cx_strfree_a(&alloc, &r);
}

mercurial