From eb787f9a5ff29686d9cd19625524afb257373608 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 28 Aug 2017 18:36:08 +0100 Subject: [PATCH] Add unit tests for custom printf --- renderdoc/serialise/utf8printf.cpp | 491 +++++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) diff --git a/renderdoc/serialise/utf8printf.cpp b/renderdoc/serialise/utf8printf.cpp index 1e3100cd8..425ed602e 100644 --- a/renderdoc/serialise/utf8printf.cpp +++ b/renderdoc/serialise/utf8printf.cpp @@ -1393,3 +1393,494 @@ int utf8printf(char *buf, size_t bufsize, const char *fmt, va_list args) return int(actualsize); } + +#if ENABLED(ENABLE_UNIT_TESTS) + +#include "3rdparty/catch/catch.hpp" + +int utf8printf_wrapper(char *buf, size_t bufsize, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + int ret = utf8printf(buf, bufsize, fmt, args); + + va_end(args); + + return ret; +} + +TEST_CASE("utf8printf buffer sizing", "[utf8printf]") +{ + int fourtytwo = 42; + int largenum = 123456; + char x = 'x'; + + SECTION("NULL input buffer") + { + int a = utf8printf_wrapper(NULL, 0, "%d %c", fourtytwo, x); + int b = snprintf(NULL, 0, "%d %c", fourtytwo, x); + + REQUIRE(a == 4); + REQUIRE(a == b); + }; + + SECTION("Too small buffer") + { + // too small buffer + char bufa[] = {0, 0, 0, 0, 0, 0}; + char bufb[] = {0, 0, 0, 0, 0, 0}; + + int a = utf8printf_wrapper(bufa, sizeof(bufa), "%d foo", largenum); + int b = snprintf(bufb, sizeof(bufb), "%d foo", largenum); + + RDCCOMPILE_ASSERT(sizeof(bufa) == 6, "bufa is mis-sized for test"); + REQUIRE(a == 10); + REQUIRE(a == b); + + char ref[] = {'1', '2', '3', '4', '5', 0}; + + RDCCOMPILE_ASSERT(sizeof(bufa) == sizeof(ref), "ref is mis-sized for test"); + + { + INFO("bufa is '" << std::string(bufa) << "', ref is '" << ref << "'"); + REQUIRE(memcmp(bufa, ref, sizeof(ref)) == 0); + } + { + INFO("bufb is '" << std::string(bufb) << "', ref is '" << ref << "'"); + REQUIRE(memcmp(bufb, ref, sizeof(ref)) == 0); + } + + SECTION("contains NULL terminator") + { + memset(bufa, 'a', sizeof(bufa)); + a = utf8printf_wrapper(bufa, sizeof(bufa), "%d foo", largenum); + INFO("bufa is '" << std::string(bufa) << "'"); + REQUIRE(memcmp(bufa, ref, sizeof(ref)) == 0); + } + }; + + SECTION("Perfectly sized buffer") + { + char bufa[12]; + char bufb[12]; + + memset(bufa, 'a', sizeof(bufa)); + memset(bufb, 'b', sizeof(bufb)); + + int a = utf8printf_wrapper(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); + int b = snprintf(bufb, sizeof(bufb), "foobar %c %d", x, fourtytwo); + + REQUIRE(a == sizeof(bufa) - 1); + REQUIRE(a == b); + + char ref[] = "foobar x 42"; + + RDCCOMPILE_ASSERT(sizeof(ref) <= sizeof(bufa), "ref is mis-sized for test"); + RDCCOMPILE_ASSERT(sizeof(ref) <= sizeof(bufb), "ref is mis-sized for test"); + + { + INFO("bufa is '" << std::string(bufa) << "', ref is '" << ref << "'"); + REQUIRE(memcmp(bufa, ref, sizeof(ref)) == 0); + } + { + INFO("bufb is '" << std::string(bufb) << "', ref is '" << ref << "'"); + REQUIRE(memcmp(bufb, ref, sizeof(ref)) == 0); + } + }; + + SECTION("Sizing accounts for implicit NULL") + { + char bufa[11]; + char bufb[11]; + + memset(bufa, 'a', sizeof(bufa)); + memset(bufb, 'b', sizeof(bufb)); + + int a = utf8printf_wrapper(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); + int b = snprintf(bufb, sizeof(bufb), "foobar %c %d", x, fourtytwo); + + REQUIRE(a == sizeof(bufa)); + REQUIRE(a == b); + + char ref[] = "foobar x 4"; + + RDCCOMPILE_ASSERT(sizeof(ref) <= sizeof(bufa), "ref is mis-sized for test"); + RDCCOMPILE_ASSERT(sizeof(ref) <= sizeof(bufb), "ref is mis-sized for test"); + + { + INFO("bufa is '" << std::string(bufa) << "', ref is '" << ref << "'"); + REQUIRE(memcmp(bufa, ref, sizeof(ref)) == 0); + } + { + INFO("bufb is '" << std::string(bufb) << "', ref is '" << ref << "'"); + REQUIRE(memcmp(bufb, ref, sizeof(ref)) == 0); + } + }; + + SECTION("Too large buffer") + { + char bufa[20]; + char bufb[20]; + + memset(bufa, 'a', sizeof(bufa)); + memset(bufb, 'b', sizeof(bufb)); + + int a = utf8printf_wrapper(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); + int b = snprintf(bufb, sizeof(bufb), "foobar %c %d", x, fourtytwo); + + REQUIRE(a == 11); + REQUIRE(a == b); + + char refa[20] = "foobar x 42\0aaaaaaa"; + char refb[20] = "foobar x 42\0bbbbbbb"; + + refa[19] = 'a'; + refb[19] = 'b'; + + { + INFO("bufa is '" << std::string(bufa) << "', refa is '" << refa << "'"); + INFO("bufa+12 is '" << std::string(bufa + 12, bufa + 20) << "', refa+12 is '" + << std::string(refa + 12, refa + 20) << "'"); + REQUIRE(memcmp(bufa, refa, sizeof(refa)) == 0); + } + { + INFO("bufb is '" << std::string(bufb) << "', refb is '" << refb << "'"); + INFO("bufb+12 is '" << std::string(bufb + 12, bufb + 20) << "', refb+12 is '" + << std::string(refb + 12, refb + 20) << "'"); + REQUIRE(memcmp(bufb, refb, sizeof(refb)) == 0); + } + }; +}; + +TEST_CASE("utf8printf standard string formatters", "[utf8printf]") +{ + const wchar_t wc = L'\xe1'; + + SECTION("Basic characters") + { + REQUIRE(StringFormat::Fmt("%c", 'a') == "a"); + REQUIRE(StringFormat::Fmt("%c", '\0') == ""); + REQUIRE(StringFormat::Fmt("%lc", wc) == "á"); + }; + + const std::string s = "ελληνικά"; + const std::wstring ws = L"\x3b5\x3bb\x3bb\x3b7\x3bd\x3b9\x3ba\x3ac"; + + SECTION("Basic strings") + { + REQUIRE(StringFormat::Fmt("%s", NULL) == "(null)"); + REQUIRE(StringFormat::Fmt("%ls", NULL) == "(null)"); + REQUIRE(StringFormat::Fmt("%s", "foobar") == "foobar"); + REQUIRE(StringFormat::Fmt("%s", "foo\0bar") == "foo"); + REQUIRE(StringFormat::Fmt("%s", s.c_str()) == s); + REQUIRE(StringFormat::Fmt("%ls", ws.c_str()) == s); + }; + + SECTION("Character padding") + { + REQUIRE(StringFormat::Fmt("%0c", 'a') == "a"); + REQUIRE(StringFormat::Fmt("%1c", 'a') == "a"); + REQUIRE(StringFormat::Fmt("%4c", 'a') == " a"); + REQUIRE(StringFormat::Fmt("%6c", 'a') == " a"); + REQUIRE(StringFormat::Fmt("%-4c", 'a') == "a "); + REQUIRE(StringFormat::Fmt("%-6c", 'a') == "a "); + }; + + SECTION("String padding") + { + REQUIRE(StringFormat::Fmt("%0s", "foobar") == "foobar"); + REQUIRE(StringFormat::Fmt("%1s", "foobar") == "foobar"); + REQUIRE(StringFormat::Fmt("%10s", "foobar") == " foobar"); + REQUIRE(StringFormat::Fmt("%-10s", "foobar") == "foobar "); + REQUIRE(StringFormat::Fmt("%10s", s.c_str()) == " " + s); + }; + + SECTION("String clipping") + { + REQUIRE(StringFormat::Fmt("%.4s", "foobar") == "foob"); + REQUIRE(StringFormat::Fmt("%.0s", "foobar") == ""); + REQUIRE(StringFormat::Fmt("%10.4s", "foobar") == " foob"); + REQUIRE(StringFormat::Fmt("%-10.4s", "foobar") == "foob "); + // these string constants take 2 bytes for each code point in UTF-8, so it's 8 bytes for 4 chars + REQUIRE(StringFormat::Fmt("%.4s", s.c_str()) == s.substr(0, 8)); + REQUIRE(StringFormat::Fmt("%.4ls", ws.c_str()) == s.substr(0, 8)); + }; +}; + +TEST_CASE("utf8printf standard integer types", "[utf8printf]") +{ + SECTION("Unsigned integers") + { + REQUIRE(StringFormat::Fmt("%hhu", uint8_t(161)) == "161"); + REQUIRE(StringFormat::Fmt("%hu", uint16_t(45502)) == "45502"); + REQUIRE(StringFormat::Fmt("%u", uint32_t(3147483647)) == "3147483647"); + REQUIRE(StringFormat::Fmt("%lu", uint32_t(3147483647)) == "3147483647"); + REQUIRE(StringFormat::Fmt("%llu", uint64_t(19813088135479LLU)) == "19813088135479"); + +#if ENABLED(RDOC_X64) + REQUIRE(StringFormat::Fmt("%zu", size_t(19813088135479LLU)) == "19813088135479"); + REQUIRE(StringFormat::Fmt("%zu", uintptr_t(19813088135479LLU)) == "19813088135479"); +#else + REQUIRE(StringFormat::Fmt("%zu", size_t(3147483647)) == "3147483647"); + REQUIRE(StringFormat::Fmt("%zu", uintptr_t(3147483647)) == "3147483647"); +#endif + }; + + SECTION("Signed integers (%d)") + { + REQUIRE(StringFormat::Fmt("%hhd", int8_t(-61)) == "-61"); + REQUIRE(StringFormat::Fmt("%hd", int16_t(-4502)) == "-4502"); + REQUIRE(StringFormat::Fmt("%d", int32_t(-1147483647)) == "-1147483647"); + REQUIRE(StringFormat::Fmt("%ld", int32_t(-1147483647)) == "-1147483647"); + REQUIRE(StringFormat::Fmt("%lld", int64_t(-19813088135479LL)) == "-19813088135479"); + +#if ENABLED(RDOC_X64) + REQUIRE(StringFormat::Fmt("%zd", intptr_t(-19813088135479LL)) == "-19813088135479"); +#else + REQUIRE(StringFormat::Fmt("%zd", intptr_t(-1147483647)) == "-1147483647"); +#endif + }; + + SECTION("Signed integers (%i)") + { + REQUIRE(StringFormat::Fmt("%hhi", int8_t(-61)) == "-61"); + REQUIRE(StringFormat::Fmt("%hi", int16_t(-4502)) == "-4502"); + REQUIRE(StringFormat::Fmt("%i", int32_t(-1147483647)) == "-1147483647"); + REQUIRE(StringFormat::Fmt("%li", int32_t(-1147483647)) == "-1147483647"); + REQUIRE(StringFormat::Fmt("%lli", int64_t(-19813088135479LL)) == "-19813088135479"); + +#if ENABLED(RDOC_X64) + REQUIRE(StringFormat::Fmt("%zi", intptr_t(-19813088135479LL)) == "-19813088135479"); +#else + REQUIRE(StringFormat::Fmt("%zi", intptr_t(-1147483647)) == "-1147483647"); +#endif + }; + + SECTION("Pointers") + { +#if ENABLED(RDOC_X64) + REQUIRE(StringFormat::Fmt("%p", (void *)NULL) == "0000000000000000"); + REQUIRE(StringFormat::Fmt("%p", (void *)(0xDEADBEEFLLU)) == "00000000DEADBEEF"); + + REQUIRE(StringFormat::Fmt("%#p", (void *)NULL) == "0x0000000000000000"); + REQUIRE(StringFormat::Fmt("%#p", (void *)(0xDEADBEEFLLU)) == "0x00000000DEADBEEF"); +#else + REQUIRE(StringFormat::Fmt("%p", (void *)NULL) == "00000000"); + REQUIRE(StringFormat::Fmt("%p", (void *)(0xDEADBEEFLLU)) == "DEADBEEF"); + + REQUIRE(StringFormat::Fmt("%#p", (void *)NULL) == "0x00000000"); + REQUIRE(StringFormat::Fmt("%#p", (void *)(0xDEADBEEFLLU)) == "0xDEADBEEF"); +#endif + }; + + SECTION("Hex") + { + REQUIRE(StringFormat::Fmt("%x", uint32_t(0x62a45f)) == "62a45f"); + REQUIRE(StringFormat::Fmt("%hx", uint16_t(0xe947)) == "e947"); + REQUIRE(StringFormat::Fmt("%llx", uint64_t(0x291f16b54ccLLU)) == "291f16b54cc"); + + REQUIRE(StringFormat::Fmt("%#x", uint32_t(0x62a45f)) == "0x62a45f"); + REQUIRE(StringFormat::Fmt("%#X", uint32_t(0x62a45f)) == "0x62A45F"); + }; + + SECTION("Binary") + { + REQUIRE(StringFormat::Fmt("%b", uint32_t(0x62a45f)) == "11000101010010001011111"); + REQUIRE(StringFormat::Fmt("%hb", uint16_t(0xe947)) == "1110100101000111"); + REQUIRE(StringFormat::Fmt("%llb", uint64_t(0x291f16b54ccLLU)) == + "101001000111110001011010110101010011001100"); + + REQUIRE(StringFormat::Fmt("%#b", uint32_t(0x62a45f)) == "0b11000101010010001011111"); + REQUIRE(StringFormat::Fmt("%#B", uint32_t(0x62a45f)) == "0B11000101010010001011111"); + }; + + SECTION("Octal") + { + REQUIRE(StringFormat::Fmt("%o", uint32_t(0627451)) == "627451"); + REQUIRE(StringFormat::Fmt("%ho", uint16_t(015477)) == "15477"); + REQUIRE(StringFormat::Fmt("%llo", uint64_t(022171675477LLU)) == "22171675477"); + REQUIRE(StringFormat::Fmt("%#o", uint32_t(0627451)) == "0627451"); + }; +}; + +TEST_CASE("utf8printf printing integer formatters", "[utf8printf]") +{ + SECTION("Sign prepending") + { + REQUIRE(StringFormat::Fmt("% u", uint32_t(123)) == "123"); + REQUIRE(StringFormat::Fmt("%+u", uint32_t(123)) == "123"); + REQUIRE(StringFormat::Fmt("% d", int32_t(123)) == " 123"); + REQUIRE(StringFormat::Fmt("%+d", int32_t(123)) == "+123"); + }; + + SECTION("Padding and alignment") + { + REQUIRE(StringFormat::Fmt("% 7u", uint32_t(123)) == " 123"); + REQUIRE(StringFormat::Fmt("%-7u", uint32_t(123)) == "123 "); + REQUIRE(StringFormat::Fmt("%-7d", int32_t(123)) == "123 "); + REQUIRE(StringFormat::Fmt("%+-7d", int32_t(123)) == "+123 "); + + REQUIRE(StringFormat::Fmt("%+7u", uint32_t(123)) == " 123"); + REQUIRE(StringFormat::Fmt("%+7d", int32_t(123)) == " +123"); + REQUIRE(StringFormat::Fmt("%+ 7d", int32_t(123)) == " +123"); + REQUIRE(StringFormat::Fmt("% +7d", int32_t(123)) == " +123"); + + REQUIRE(StringFormat::Fmt("%07u", uint32_t(123)) == "0000123"); + REQUIRE(StringFormat::Fmt("%-07u", uint32_t(123)) == "123 "); + + REQUIRE(StringFormat::Fmt("%07d", int32_t(123)) == "0000123"); + REQUIRE(StringFormat::Fmt("%-07d", int32_t(123)) == "123 "); + + REQUIRE(StringFormat::Fmt("%+07d", int32_t(123)) == "+000123"); + REQUIRE(StringFormat::Fmt("%+-07d", int32_t(123)) == "+123 "); + + REQUIRE(StringFormat::Fmt("%3d", int32_t(123456)) == "123456"); + REQUIRE(StringFormat::Fmt("%03d", int32_t(123456)) == "123456"); + REQUIRE(StringFormat::Fmt("%-3d", int32_t(123456)) == "123456"); + + REQUIRE(StringFormat::Fmt("%3d", int32_t(-123456)) == "-123456"); + REQUIRE(StringFormat::Fmt("%03d", int32_t(-123456)) == "-123456"); + REQUIRE(StringFormat::Fmt("%-3d", int32_t(-123456)) == "-123456"); + + REQUIRE(StringFormat::Fmt("% 7x", uint32_t(0x123)) == " 123"); + REQUIRE(StringFormat::Fmt("%-7x", uint32_t(0x123)) == "123 "); + REQUIRE(StringFormat::Fmt("%07x", uint32_t(0x123)) == "0000123"); + + REQUIRE(StringFormat::Fmt("%# 7x", uint32_t(0x123)) == " 0x123"); + REQUIRE(StringFormat::Fmt("%#-7x", uint32_t(0x123)) == "0x123 "); + REQUIRE(StringFormat::Fmt("%#07x", uint32_t(0x123)) == "0x00123"); + }; + + SECTION("Precision") + { + REQUIRE(StringFormat::Fmt("%.3d", int32_t(123456)) == "123456"); + REQUIRE(StringFormat::Fmt("%3.3d", int32_t(123456)) == "123456"); + REQUIRE(StringFormat::Fmt("%.9d", int32_t(123456)) == "000123456"); + }; +}; + +TEST_CASE("utf8printf printing floats", "[utf8printf]") +{ + volatile float zero = 0.0f; + volatile float one = 1.0f; + volatile float negone = -1.0f; + + SECTION("Specials") + { + REQUIRE(StringFormat::Fmt("%f", one / zero) == "+inf"); + REQUIRE(StringFormat::Fmt("%f", negone / zero) == "-inf"); + REQUIRE(StringFormat::Fmt("%f", sqrt(negone)) == "nan"); + REQUIRE(StringFormat::Fmt("%f", -sqrt(negone)) == "nan"); + + REQUIRE(StringFormat::Fmt("%F", one / zero) == "+INF"); + REQUIRE(StringFormat::Fmt("%F", negone / zero) == "-INF"); + REQUIRE(StringFormat::Fmt("%F", sqrt(negone)) == "NAN"); + REQUIRE(StringFormat::Fmt("%F", -sqrt(negone)) == "NAN"); + } + + SECTION("Basic numbers as %f") + { + REQUIRE(StringFormat::Fmt("%f", 0.0) == "0.000000"); + REQUIRE(StringFormat::Fmt("%f", 1.0) == "1.000000"); + REQUIRE(StringFormat::Fmt("%f", 2.0) == "2.000000"); + REQUIRE(StringFormat::Fmt("%f", 3.0) == "3.000000"); + REQUIRE(StringFormat::Fmt("%f", 5.0) == "5.000000"); + REQUIRE(StringFormat::Fmt("%f", 0.1) == "0.100000"); + REQUIRE(StringFormat::Fmt("%f", 0.2) == "0.200000"); + REQUIRE(StringFormat::Fmt("%f", 0.3) == "0.300000"); + REQUIRE(StringFormat::Fmt("%f", 0.5) == "0.500000"); + REQUIRE(StringFormat::Fmt("%f", 1.234567890123456) == "1.234568"); + REQUIRE(StringFormat::Fmt("%f", 1.234567123456) == "1.234567"); + REQUIRE(StringFormat::Fmt("%f", 12345671234.56) == "12345671234.560000"); + REQUIRE(StringFormat::Fmt("%f", 12345671234.56e+20) == + "1234567123456000000000000000000.000000"); + REQUIRE(StringFormat::Fmt("%f", 12345671234.56e-20) == "0.000000"); + }; + + SECTION("Basic numbers as %e") + { + REQUIRE(StringFormat::Fmt("%e", 0.0) == "0.000000e+000"); + REQUIRE(StringFormat::Fmt("%e", 1.0) == "1.000000e+000"); + REQUIRE(StringFormat::Fmt("%e", 2.0) == "2.000000e+000"); + REQUIRE(StringFormat::Fmt("%e", 3.0) == "3.000000e+000"); + REQUIRE(StringFormat::Fmt("%e", 5.0) == "5.000000e+000"); + REQUIRE(StringFormat::Fmt("%e", 0.1) == "1.000000e-001"); + REQUIRE(StringFormat::Fmt("%e", 0.2) == "2.000000e-001"); + REQUIRE(StringFormat::Fmt("%e", 0.3) == "3.000000e-001"); + REQUIRE(StringFormat::Fmt("%e", 0.5) == "5.000000e-001"); + REQUIRE(StringFormat::Fmt("%e", 1.234567890123456) == "1.234568e+000"); + REQUIRE(StringFormat::Fmt("%e", 1.234567123456) == "1.234567e+000"); + REQUIRE(StringFormat::Fmt("%e", 12345671234.56) == "1.234567e+010"); + REQUIRE(StringFormat::Fmt("%e", 12345671234.56e+20) == "1.234567e+030"); + REQUIRE(StringFormat::Fmt("%e", 12345671234.56e-20) == "1.234567e-010"); + }; + + SECTION("Basic numbers as %g") + { + REQUIRE(StringFormat::Fmt("%g", 0.0) == "0"); + REQUIRE(StringFormat::Fmt("%g", 1.0) == "1"); + REQUIRE(StringFormat::Fmt("%g", 2.0) == "2"); + REQUIRE(StringFormat::Fmt("%g", 3.0) == "3"); + REQUIRE(StringFormat::Fmt("%g", 5.0) == "5"); + REQUIRE(StringFormat::Fmt("%g", 0.1) == "0.1"); + REQUIRE(StringFormat::Fmt("%g", 0.2) == "0.2"); + REQUIRE(StringFormat::Fmt("%g", 0.3) == "0.3"); + REQUIRE(StringFormat::Fmt("%g", 0.5) == "0.5"); + REQUIRE(StringFormat::Fmt("%g", 1.234567890123456) == "1.23457"); + REQUIRE(StringFormat::Fmt("%g", 1.23456123456) == "1.23456"); + REQUIRE(StringFormat::Fmt("%g", 12345671234.56) == "1.23457e+010"); + REQUIRE(StringFormat::Fmt("%g", 12345671234.56e+20) == "1.23457e+030"); + REQUIRE(StringFormat::Fmt("%g", 12345671234.56e-20) == "1.23457e-010"); + }; + + SECTION("Rounding") + { + REQUIRE(StringFormat::Fmt("%.4e", 0.12345222) == "1.2345e-001"); + REQUIRE(StringFormat::Fmt("%.5f", 0.12345222) == "0.12345"); + REQUIRE(StringFormat::Fmt("%.5g", 0.12345222) == "0.12345"); + + REQUIRE(StringFormat::Fmt("%.4e", 0.12345888) == "1.2346e-001"); + REQUIRE(StringFormat::Fmt("%.5f", 0.12345888) == "0.12346"); + REQUIRE(StringFormat::Fmt("%.5g", 0.12345888) == "0.12346"); + + REQUIRE(StringFormat::Fmt("%.5f", 0.00000222) == "0.00000"); + REQUIRE(StringFormat::Fmt("%.5f", 0.00000888) == "0.00001"); + REQUIRE(StringFormat::Fmt("%.5f", 0.00000000222) == "0.00000"); + + REQUIRE(StringFormat::Fmt("%.5f", 0.000888) == "0.00089"); + REQUIRE(StringFormat::Fmt("%.5f", 0.0000888) == "0.00009"); + REQUIRE(StringFormat::Fmt("%.5f", 0.00000888) == "0.00001"); + REQUIRE(StringFormat::Fmt("%.5f", 0.000000888) == "0.00000"); + REQUIRE(StringFormat::Fmt("%.10f", 0.000000888) == "0.0000008880"); + }; + + SECTION("Always decimal flag") + { + REQUIRE(StringFormat::Fmt("%@g", 0.0) == "0.0"); + REQUIRE(StringFormat::Fmt("%@g", 1.0) == "1.0"); + REQUIRE(StringFormat::Fmt("%@g", 2.0) == "2.0"); + REQUIRE(StringFormat::Fmt("%@g", 3.0) == "3.0"); + REQUIRE(StringFormat::Fmt("%@g", 5.0) == "5.0"); + }; + + SECTION("Precision") + { + REQUIRE(StringFormat::Fmt("%.3f", 0.0) == "0.000"); + REQUIRE(StringFormat::Fmt("%.3f", 1.0) == "1.000"); + REQUIRE(StringFormat::Fmt("%.3f", 2.0) == "2.000"); + REQUIRE(StringFormat::Fmt("%.3f", 0.1) == "0.100"); + REQUIRE(StringFormat::Fmt("%.3f", 0.2) == "0.200"); + REQUIRE(StringFormat::Fmt("%.3f", 1.2313) == "1.231"); + }; + + SECTION("Padding") + { + REQUIRE(StringFormat::Fmt("%5.3f", 1.0) == "1.000"); + REQUIRE(StringFormat::Fmt("%10.3f", 1.0) == " 1.000"); + REQUIRE(StringFormat::Fmt("%-10.3f", 1.0) == "1.000 "); + REQUIRE(StringFormat::Fmt("%010.3f", 1.0) == "000001.000"); + }; +}; + +#endif // ENABLED(ENABLE_UNIT_TESTS)