#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);
}