This is a maintenance fork
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

653 lines
30 KiB

/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
╚══════════════════════════════════════════════════════════════════════════════╝
│ @author (c) Marco Paland (info@paland.com) │
│ 2014-2019, PALANDesign Hannover, Germany │
│ │
│ @license The MIT License (MIT) │
│ │
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
│ of this software and associated documentation files (the "Software"), to deal│
│ in the Software without restriction, including without limitation the rights │
│ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell │
│ copies of the Software, and to permit persons to whom the Software is │
│ furnished to do so, subject to the following conditions: │
│ │
│ The above copyright notice and this permission notice shall be included in │
│ all copies or substantial portions of the Software. │
│ │
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,│
│ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN │
│ THE SOFTWARE. │
└─────────────────────────────────────────────────────────────────────────────*/
#include "libc/bits/progn.h"
#include "libc/bits/pushpop.h"
#include "libc/bits/safemacros.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
static char buffer[128];
#define Format(...) PROGN(snprintf(buffer, sizeof(buffer), __VA_ARGS__), buffer)
TEST(sprintf, test_space_flag) {
EXPECT_STREQ(" 42", Format("% d", 42));
EXPECT_STREQ("-42", Format("% d", -42));
EXPECT_STREQ(" 42", Format("% 5d", 42));
EXPECT_STREQ(" -42", Format("% 5d", -42));
EXPECT_STREQ(" 42", Format("% 15d", 42));
EXPECT_STREQ(" -42", Format("% 15d", -42));
EXPECT_STREQ(" -42", Format("% 15d", -42));
EXPECT_STREQ(" -42.987", Format("% 15.3f", -42.987));
EXPECT_STREQ(" 42.987", Format("% 15.3f", 42.987));
EXPECT_STREQ("Hello testing", Format("% s", "Hello testing"));
EXPECT_STREQ(" 1024", Format("% d", 1024));
EXPECT_STREQ("-1024", Format("% d", -1024));
EXPECT_STREQ(" 1024", Format("% i", 1024));
EXPECT_STREQ("-1024", Format("% i", -1024));
EXPECT_STREQ("1024", Format("% u", 1024));
EXPECT_STREQ("4294966272", Format("% u", 4294966272U));
EXPECT_STREQ("777", Format("% o", 511));
EXPECT_STREQ("37777777001", Format("% o", 4294966785U));
EXPECT_STREQ("1234abcd", Format("% x", 305441741));
EXPECT_STREQ("edcb5433", Format("% x", 3989525555U));
EXPECT_STREQ("1234ABCD", Format("% X", 305441741));
EXPECT_STREQ("EDCB5433", Format("% X", 3989525555U));
EXPECT_STREQ("x", Format("% c", 'x'));
}
TEST(sprintf, test_plus_flag) {
EXPECT_STREQ("+42", Format("%+d", 42));
EXPECT_STREQ("-42", Format("%+d", -42));
EXPECT_STREQ(" +42", Format("%+5d", 42));
EXPECT_STREQ(" -42", Format("%+5d", -42));
EXPECT_STREQ(" +42", Format("%+15d", 42));
EXPECT_STREQ(" -42", Format("%+15d", -42));
EXPECT_STREQ("+1024", Format("%+d", 1024));
EXPECT_STREQ("-1024", Format("%+d", -1024));
EXPECT_STREQ("+1024", Format("%+i", 1024));
EXPECT_STREQ("-1024", Format("%+i", -1024));
EXPECT_STREQ("1024", Format("%+u", 1024));
EXPECT_STREQ("4294966272", Format("%+u", 4294966272U));
EXPECT_STREQ("777", Format("%+o", 511));
EXPECT_STREQ("37777777001", Format("%+o", 4294966785U));
EXPECT_STREQ("1234abcd", Format("%+x", 305441741));
EXPECT_STREQ("edcb5433", Format("%+x", 3989525555U));
EXPECT_STREQ("1234ABCD", Format("%+X", 305441741));
EXPECT_STREQ("EDCB5433", Format("%+X", 3989525555U));
EXPECT_STREQ("+", Format("%+.0d", 0));
}
TEST(sprintf, test_flag0) {
EXPECT_STREQ("42", Format("%0d", 42));
EXPECT_STREQ("42", Format("%0ld", 42L));
EXPECT_STREQ("-42", Format("%0d", -42));
EXPECT_STREQ("00042", Format("%05d", 42));
EXPECT_STREQ("-0042", Format("%05d", -42));
EXPECT_STREQ("000000000000042", Format("%015d", 42));
EXPECT_STREQ("-00000000000042", Format("%015d", -42));
EXPECT_STREQ("000000000042.12", Format("%015.2f", 42.1234));
EXPECT_STREQ("00000000042.988", Format("%015.3f", 42.9876));
EXPECT_STREQ("-00000042.98760", Format("%015.5f", -42.9876));
}
TEST(sprintf, test_flag_minus) {
EXPECT_STREQ("42", Format("%-d", 42));
EXPECT_STREQ("-42", Format("%-d", -42));
EXPECT_STREQ("42 ", Format("%-5d", 42));
EXPECT_STREQ("-42 ", Format("%-5d", -42));
EXPECT_STREQ("42 ", Format("%-15d", 42));
EXPECT_STREQ("-42 ", Format("%-15d", -42));
EXPECT_STREQ("42", Format("%-0d", 42));
EXPECT_STREQ("-42", Format("%-0d", -42));
EXPECT_STREQ("42 ", Format("%-05d", 42));
EXPECT_STREQ("-42 ", Format("%-05d", -42));
EXPECT_STREQ("42 ", Format("%-015d", 42));
EXPECT_STREQ("-42 ", Format("%-015d", -42));
EXPECT_STREQ("42", Format("%0-d", 42));
EXPECT_STREQ("-42", Format("%0-d", -42));
EXPECT_STREQ("42 ", Format("%0-5d", 42));
EXPECT_STREQ("-42 ", Format("%0-5d", -42));
EXPECT_STREQ("42 ", Format("%0-15d", 42));
EXPECT_STREQ("-42 ", Format("%0-15d", -42));
}
TEST(sprintf, testAlternativeFormatting) {
EXPECT_STREQ("0", Format("%#x", 0));
EXPECT_STREQ("", Format("%#.0x", 0));
EXPECT_STREQ("0", Format("%#.1x", 0));
EXPECT_STREQ("", Format("%#.0llx", (long long)0));
EXPECT_STREQ("0x0000614e", Format("%#.8x", 0x614e));
EXPECT_STREQ("0b110", Format("%#b", 6));
}
TEST(sprintf, testHexBasePrefix_onlyConsumesLeadingZeroes) {
/* TODO(jart): Upstream bug fix for this behavior. */
EXPECT_STREQ("0x01", Format("%#04x", 0x1));
EXPECT_STREQ("0x12", Format("%#04x", 0x12));
EXPECT_STREQ("0x123", Format("%#04x", 0x123));
EXPECT_STREQ("0x1234", Format("%#04x", 0x1234));
}
TEST(sprintf, testBinaryBasePrefix_onlyConsumesLeadingZeroes) {
EXPECT_STREQ("0b01", Format("%#04b", 0b1));
EXPECT_STREQ("0b10", Format("%#04b", 0b10));
EXPECT_STREQ("0b101", Format("%#04b", 0b101));
EXPECT_STREQ("0b1010", Format("%#04b", 0b1010));
}
TEST(sprintf, testOctalBasePrefix_onlyConsumesLeadingZeroes) {
EXPECT_STREQ("0001", Format("%#04o", 01));
EXPECT_STREQ("0010", Format("%#04o", 010));
EXPECT_STREQ("0101", Format("%#04o", 0101));
EXPECT_STREQ("01010", Format("%#04o", 01010));
}
TEST(sprintf, test_specifier) {
EXPECT_STREQ("Hello testing", Format("Hello testing"));
EXPECT_STREQ("Hello testing", Format("%s", "Hello testing"));
EXPECT_STREQ("1024", Format("%d", 1024));
EXPECT_STREQ("-1024", Format("%d", -1024));
EXPECT_STREQ("1024", Format("%i", 1024));
EXPECT_STREQ("-1024", Format("%i", -1024));
EXPECT_STREQ("1024", Format("%u", 1024));
EXPECT_STREQ("4294966272", Format("%u", 4294966272U));
EXPECT_STREQ("777", Format("%o", 511));
EXPECT_STREQ("37777777001", Format("%o", 4294966785U));
EXPECT_STREQ("1234abcd", Format("%x", 305441741));
EXPECT_STREQ("edcb5433", Format("%x", 3989525555U));
EXPECT_STREQ("1234ABCD", Format("%X", 305441741));
EXPECT_STREQ("EDCB5433", Format("%X", 3989525555U));
EXPECT_STREQ("%", Format("%%"));
}
TEST(sprintf, test_width) {
EXPECT_STREQ("Hello testing", Format("%1s", "Hello testing"));
EXPECT_STREQ("1024", Format("%1d", 1024));
EXPECT_STREQ("-1024", Format("%1d", -1024));
EXPECT_STREQ("1024", Format("%1i", 1024));
EXPECT_STREQ("-1024", Format("%1i", -1024));
EXPECT_STREQ("1024", Format("%1u", 1024));
EXPECT_STREQ("4294966272", Format("%1u", 4294966272U));
EXPECT_STREQ("777", Format("%1o", 511));
EXPECT_STREQ("37777777001", Format("%1o", 4294966785U));
EXPECT_STREQ("1234abcd", Format("%1x", 305441741));
EXPECT_STREQ("edcb5433", Format("%1x", 3989525555U));
EXPECT_STREQ("1234ABCD", Format("%1X", 305441741));
EXPECT_STREQ("EDCB5433", Format("%1X", 3989525555U));
EXPECT_STREQ("x", Format("%1c", 'x'));
}
TEST(sprintf, test_width_20) {
/* TODO(jart): wut */
/* sprintf(buffer, "%20s", "Hello"); */
/* printf("'%s' %d\n", buffer, strlen(buffer)); */
/* EXPECT_STREQ(" Hello", buffer); */
EXPECT_STREQ(" 1024", Format("%20d", 1024));
EXPECT_STREQ(" -1024", Format("%20d", -1024));
EXPECT_STREQ(" 1024", Format("%20i", 1024));
EXPECT_STREQ(" -1024", Format("%20i", -1024));
EXPECT_STREQ(" 1024", Format("%20u", 1024));
EXPECT_STREQ(" 4294966272", Format("%20u", 4294966272U));
EXPECT_STREQ(" 777", Format("%20o", 511));
EXPECT_STREQ(" 37777777001", Format("%20o", 4294966785U));
EXPECT_STREQ(" 1234abcd", Format("%20x", 305441741));
EXPECT_STREQ(" edcb5433", Format("%20x", 3989525555U));
EXPECT_STREQ(" 1234ABCD", Format("%20X", 305441741));
EXPECT_STREQ(" EDCB5433", Format("%20X", 3989525555U));
EXPECT_STREQ(" x", Format("%20c", 'x'));
}
TEST(sprintf, test_width_star_20) {
EXPECT_STREQ(" Hello", Format("%*s", 20, "Hello"));
EXPECT_STREQ(" 1024", Format("%*d", 20, 1024));
EXPECT_STREQ(" -1024", Format("%*d", 20, -1024));
EXPECT_STREQ(" 1024", Format("%*i", 20, 1024));
EXPECT_STREQ(" -1024", Format("%*i", 20, -1024));
EXPECT_STREQ(" 1024", Format("%*u", 20, 1024));
EXPECT_STREQ(" 4294966272", Format("%*u", 20, 4294966272U));
EXPECT_STREQ(" 777", Format("%*o", 20, 511));
EXPECT_STREQ(" 37777777001", Format("%*o", 20, 4294966785U));
EXPECT_STREQ(" 1234abcd", Format("%*x", 20, 305441741));
EXPECT_STREQ(" edcb5433", Format("%*x", 20, 3989525555U));
EXPECT_STREQ(" 1234ABCD", Format("%*X", 20, 305441741));
EXPECT_STREQ(" EDCB5433", Format("%*X", 20, 3989525555U));
EXPECT_STREQ(" x", Format("%*c", 20, 'x'));
}
TEST(sprintf, test_width_minus_20) {
EXPECT_STREQ("Hello ", Format("%-20s", "Hello"));
EXPECT_STREQ("1024 ", Format("%-20d", 1024));
EXPECT_STREQ("-1024 ", Format("%-20d", -1024));
EXPECT_STREQ("1024 ", Format("%-20i", 1024));
EXPECT_STREQ("-1024 ", Format("%-20i", -1024));
EXPECT_STREQ("1024 ", Format("%-20u", 1024));
EXPECT_STREQ("1024.1234 ", Format("%-20.4f", 1024.1234));
EXPECT_STREQ("4294966272 ", Format("%-20u", 4294966272U));
EXPECT_STREQ("777 ", Format("%-20o", 511));
EXPECT_STREQ("37777777001 ", Format("%-20o", 4294966785U));
EXPECT_STREQ("1234abcd ", Format("%-20x", 305441741));
EXPECT_STREQ("edcb5433 ", Format("%-20x", 3989525555U));
EXPECT_STREQ("1234ABCD ", Format("%-20X", 305441741));
EXPECT_STREQ("EDCB5433 ", Format("%-20X", 3989525555U));
EXPECT_STREQ("x ", Format("%-20c", 'x'));
EXPECT_STREQ("| 9| |9 | | 9|", Format("|%5d| |%-2d| |%5d|", 9, 9, 9));
EXPECT_STREQ("| 10| |10| | 10|",
Format("|%5d| |%-2d| |%5d|", 10, 10, 10));
EXPECT_STREQ("| 9| |9 | | 9|",
Format("|%5d| |%-12d| |%5d|", 9, 9, 9));
EXPECT_STREQ("| 10| |10 | | 10|",
Format("|%5d| |%-12d| |%5d|", 10, 10, 10));
}
TEST(sprintf, test_width_0_minus_20) {
EXPECT_STREQ("Hello ", Format("%0-20s", "Hello"));
EXPECT_STREQ("1024 ", Format("%0-20d", 1024));
EXPECT_STREQ("-1024 ", Format("%0-20d", -1024));
EXPECT_STREQ("1024 ", Format("%0-20i", 1024));
EXPECT_STREQ("-1024 ", Format("%0-20i", -1024));
EXPECT_STREQ("1024 ", Format("%0-20u", 1024));
EXPECT_STREQ("4294966272 ", Format("%0-20u", 4294966272U));
EXPECT_STREQ("777 ", Format("%0-20o", 511));
EXPECT_STREQ("37777777001 ", Format("%0-20o", 4294966785U));
EXPECT_STREQ("1234abcd ", Format("%0-20x", 305441741));
EXPECT_STREQ("edcb5433 ", Format("%0-20x", 3989525555U));
EXPECT_STREQ("1234ABCD ", Format("%0-20X", 305441741));
EXPECT_STREQ("EDCB5433 ", Format("%0-20X", 3989525555U));
EXPECT_STREQ("x ", Format("%0-20c", 'x'));
}
TEST(sprintf, test_padding_20) {
EXPECT_STREQ("00000000000000001024", Format("%020d", 1024));
EXPECT_STREQ("-0000000000000001024", Format("%020d", -1024));
EXPECT_STREQ("00000000000000001024", Format("%020i", 1024));
EXPECT_STREQ("-0000000000000001024", Format("%020i", -1024));
EXPECT_STREQ("00000000000000001024", Format("%020u", 1024));
EXPECT_STREQ("00000000004294966272", Format("%020u", 4294966272U));
EXPECT_STREQ("00000000000000000777", Format("%020o", 511));
EXPECT_STREQ("00000000037777777001", Format("%020o", 4294966785U));
EXPECT_STREQ("0000000000001234abcd", Format("%020x", 305441741));
EXPECT_STREQ("000000000000edcb5433", Format("%020x", 3989525555U));
EXPECT_STREQ("0000000000001234ABCD", Format("%020X", 305441741));
EXPECT_STREQ("000000000000EDCB5433", Format("%020X", 3989525555U));
}
TEST(sprintf, test_padding_dot_20) {
EXPECT_STREQ("00000000000000001024", Format("%.20d", 1024));
EXPECT_STREQ("-00000000000000001024", Format("%.20d", -1024));
EXPECT_STREQ("00000000000000001024", Format("%.20i", 1024));
EXPECT_STREQ("-00000000000000001024", Format("%.20i", -1024));
EXPECT_STREQ("00000000000000001024", Format("%.20u", 1024));
EXPECT_STREQ("00000000004294966272", Format("%.20u", 4294966272U));
EXPECT_STREQ("00000000000000000777", Format("%.20o", 511));
EXPECT_STREQ("00000000037777777001", Format("%.20o", 4294966785U));
EXPECT_STREQ("0000000000001234abcd", Format("%.20x", 305441741));
EXPECT_STREQ("000000000000edcb5433", Format("%.20x", 3989525555U));
EXPECT_STREQ("0000000000001234ABCD", Format("%.20X", 305441741));
EXPECT_STREQ("000000000000EDCB5433", Format("%.20X", 3989525555U));
}
TEST(sprintf, test_padding_pound_020) {
EXPECT_STREQ("00000000000000001024", Format("%#020d", 1024));
EXPECT_STREQ("-0000000000000001024", Format("%#020d", -1024));
EXPECT_STREQ("00000000000000001024", Format("%#020i", 1024));
EXPECT_STREQ("-0000000000000001024", Format("%#020i", -1024));
EXPECT_STREQ("00000000000000001024", Format("%#020u", 1024));
EXPECT_STREQ("00000000004294966272", Format("%#020u", 4294966272U));
EXPECT_STREQ("00000000000000000777", Format("%#020o", 511));
EXPECT_STREQ("00000000037777777001", Format("%#020o", 4294966785U));
EXPECT_STREQ("0x00000000001234abcd", Format("%#020x", 305441741));
EXPECT_STREQ("0x0000000000edcb5433", Format("%#020x", 3989525555U));
EXPECT_STREQ("0x00000000001234ABCD", Format("%#020X", 305441741));
EXPECT_STREQ("0x0000000000EDCB5433", Format("%#020X", 3989525555U));
}
TEST(sprintf, test_padding_pound_20) {
EXPECT_STREQ(" 1024", Format("%#20d", 1024));
EXPECT_STREQ(" -1024", Format("%#20d", -1024));
EXPECT_STREQ(" 1024", Format("%#20i", 1024));
EXPECT_STREQ(" -1024", Format("%#20i", -1024));
EXPECT_STREQ(" 1024", Format("%#20u", 1024));
EXPECT_STREQ(" 4294966272", Format("%#20u", 4294966272U));
EXPECT_STREQ(" 0777", Format("%#20o", 511));
EXPECT_STREQ(" 037777777001", Format("%#20o", 4294966785U));
EXPECT_STREQ(" 0x1234abcd", Format("%#20x", 305441741));
EXPECT_STREQ(" 0xedcb5433", Format("%#20x", 3989525555U));
EXPECT_STREQ(" 0x1234ABCD", Format("%#20X", 305441741));
EXPECT_STREQ(" 0xEDCB5433", Format("%#20X", 3989525555U));
}
TEST(sprintf, test_padding_20_point_5) {
EXPECT_STREQ(" 01024", Format("%20.5d", 1024));
EXPECT_STREQ(" -01024", Format("%20.5d", -1024));
EXPECT_STREQ(" 01024", Format("%20.5i", 1024));
EXPECT_STREQ(" -01024", Format("%20.5i", -1024));
EXPECT_STREQ(" 01024", Format("%20.5u", 1024));
EXPECT_STREQ(" 4294966272", Format("%20.5u", 4294966272U));
EXPECT_STREQ(" 00777", Format("%20.5o", 511));
EXPECT_STREQ(" 37777777001", Format("%20.5o", 4294966785U));
EXPECT_STREQ(" 1234abcd", Format("%20.5x", 305441741));
EXPECT_STREQ(" 00edcb5433", Format("%20.10x", 3989525555U));
EXPECT_STREQ(" 1234ABCD", Format("%20.5X", 305441741));
EXPECT_STREQ(" 00EDCB5433", Format("%20.10X", 3989525555U));
}
TEST(sprintf, test_padding_neg_numbers) {
/* space padding */
EXPECT_STREQ("-5", Format("% 1d", -5));
EXPECT_STREQ("-5", Format("% 2d", -5));
EXPECT_STREQ(" -5", Format("% 3d", -5));
EXPECT_STREQ(" -5", Format("% 4d", -5));
/* zero padding */
EXPECT_STREQ("-5", Format("%01d", -5));
EXPECT_STREQ("-5", Format("%02d", -5));
EXPECT_STREQ("-05", Format("%03d", -5));
EXPECT_STREQ("-005", Format("%04d", -5));
}
TEST(sprintf, test_float_padding_neg_numbers) {
/* space padding */
EXPECT_STREQ("-5.0", Format("% 3.1f", -5.));
EXPECT_STREQ("-5.0", Format("% 4.1f", -5.));
EXPECT_STREQ(" -5.0", Format("% 5.1f", -5.));
/* zero padding */
EXPECT_STREQ("-5.0", Format("%03.1f", -5.));
EXPECT_STREQ("-5.0", Format("%04.1f", -5.));
EXPECT_STREQ("-05.0", Format("%05.1f", -5.));
/* zero padding no decimal point */
EXPECT_STREQ("-5", Format("%01.0f", -5.));
EXPECT_STREQ("-5", Format("%02.0f", -5.));
EXPECT_STREQ("-05", Format("%03.0f", -5.));
}
TEST(sprintf, test_length) {
EXPECT_STREQ("", Format("%.0s", "Hello testing"));
EXPECT_STREQ(" ", Format("%20.0s", "Hello testing"));
EXPECT_STREQ("", Format("%.s", "Hello testing"));
EXPECT_STREQ(" ", Format("%20.s", "Hello testing"));
EXPECT_STREQ(" 1024", Format("%20.0d", 1024));
EXPECT_STREQ(" -1024", Format("%20.0d", -1024));
EXPECT_STREQ(" ", Format("%20.d", 0));
EXPECT_STREQ(" 1024", Format("%20.0i", 1024));
EXPECT_STREQ(" -1024", Format("%20.i", -1024));
EXPECT_STREQ(" ", Format("%20.i", 0));
EXPECT_STREQ(" 1024", Format("%20.u", 1024));
EXPECT_STREQ(" 4294966272", Format("%20.0u", 4294966272U));
EXPECT_STREQ(" ", Format("%20.u", 0U));
EXPECT_STREQ(" 777", Format("%20.o", 511));
EXPECT_STREQ(" 37777777001", Format("%20.0o", 4294966785U));
EXPECT_STREQ(" ", Format("%20.o", 0U));
EXPECT_STREQ(" 1234abcd", Format("%20.x", 305441741));
EXPECT_STREQ(" 1234abcd",
Format("%50.x", 305441741));
EXPECT_STREQ(" 1234abcd 12345",
Format("%50.x%10.u", 305441741, 12345));
EXPECT_STREQ(" edcb5433", Format("%20.0x", 3989525555U));
EXPECT_STREQ(" ", Format("%20.x", 0U));
EXPECT_STREQ(" 1234ABCD", Format("%20.X", 305441741));
EXPECT_STREQ(" EDCB5433", Format("%20.0X", 3989525555U));
EXPECT_STREQ(" ", Format("%20.X", 0U));
EXPECT_STREQ(" ", Format("%02.0u", 0U));
EXPECT_STREQ(" ", Format("%02.0d", 0));
}
TEST(sprintf, test_float) {
#ifndef __FINITE_MATH_ONLY__
EXPECT_STREQ("nan", Format("%.4f", NAN));
#endif
EXPECT_STREQ("3.1415", Format("%.4f", 3.1415354));
EXPECT_STREQ("30343.142", Format("%.3f", 30343.1415354));
EXPECT_STREQ("34", Format("%.0f", 34.1415354));
EXPECT_STREQ("1", Format("%.0f", 1.3));
EXPECT_STREQ("2", Format("%.0f", 1.55));
EXPECT_STREQ("1.6", Format("%.1f", 1.64));
EXPECT_STREQ("42.90", Format("%.2f", 42.8952));
EXPECT_STREQ("42.895200000", Format("%.9f", 42.8952));
EXPECT_STREQ("42.8952230000", Format("%.10f", 42.895223));
/* this testcase checks, that the precision is truncated to 9 digits. */
/* a perfect working float should return the whole number */
EXPECT_STREQ("42.895223123000", Format("%.12f", 42.89522312345678));
/* this testcase checks, that the precision is truncated AND rounded to 9 */
/* digits. a perfect working float should return the whole number */
EXPECT_STREQ("42.895223877000", Format("%.12f", 42.89522387654321));
EXPECT_STREQ(" 42.90", Format("%6.2f", 42.8952));
EXPECT_STREQ("+42.90", Format("%+6.2f", 42.8952));
EXPECT_STREQ("+42.9", Format("%+5.1f", 42.9252));
EXPECT_STREQ("42.500000", Format("%f", 42.5));
EXPECT_STREQ("42.5", Format("%.1f", 42.5));
EXPECT_STREQ("42167.000000", Format("%f", 42167.0));
EXPECT_STREQ("-12345.987654321", Format("%.9f", -12345.987654321));
EXPECT_STREQ("4.0", Format("%.1f", 3.999));
EXPECT_STREQ("4", Format("%.0f", 3.5));
EXPECT_STREQ("4", Format("%.0f", 4.5));
EXPECT_STREQ("3", Format("%.0f", 3.49));
EXPECT_STREQ("3.5", Format("%.1f", 3.49));
EXPECT_STREQ("a0.5 ", Format("a%-5.1f", 0.5));
EXPECT_STREQ("a0.5 end", Format("a%-5.1fend", 0.5));
/* out of range in the moment, need to be fixed by someone */
EXPECT_STREQ("inf", Format("%.1f", 1E20));
}
TEST(sprintf, test_types) {
EXPECT_STREQ("0", Format("%i", 0));
EXPECT_STREQ("1234", Format("%i", 1234));
EXPECT_STREQ("32767", Format("%i", 32767));
EXPECT_STREQ("-32767", Format("%i", -32767));
EXPECT_STREQ("30", Format("%li", 30L));
EXPECT_STREQ("-2147483647", Format("%li", -2147483647L));
EXPECT_STREQ("2147483647", Format("%li", 2147483647L));
EXPECT_STREQ("30", Format("%lli", 30LL));
EXPECT_STREQ("-9223372036854775807", Format("%lli", -9223372036854775807LL));
EXPECT_STREQ("9223372036854775807", Format("%lli", 9223372036854775807LL));
EXPECT_STREQ("100000", Format("%lu", 100000L));
EXPECT_STREQ("4294967295", Format("%lu", 0xFFFFFFFFL));
EXPECT_STREQ("281474976710656", Format("%llu", 281474976710656LLU));
EXPECT_STREQ("18446744073709551615", Format("%llu", 18446744073709551615LLU));
EXPECT_STREQ("2147483647", Format("%zu", 2147483647UL));
EXPECT_STREQ("2147483647", Format("%zd", 2147483647UL));
if (sizeof(size_t) == sizeof(long)) {
EXPECT_STREQ("-2147483647", Format("%zi", -2147483647L));
} else {
EXPECT_STREQ("-2147483647", Format("%zi", -2147483647LL));
}
EXPECT_STREQ("1110101001100000", Format("%b", 60000));
EXPECT_STREQ("101111000110000101001110", Format("%lb", 12345678L));
EXPECT_STREQ("165140", Format("%o", 60000));
EXPECT_STREQ("57060516", Format("%lo", 12345678L));
EXPECT_STREQ("12345678", Format("%lx", 0x12345678L));
EXPECT_STREQ("1234567891234567", Format("%llx", 0x1234567891234567LLU));
EXPECT_STREQ("abcdefab", Format("%lx", 0xabcdefabL));
EXPECT_STREQ("ABCDEFAB", Format("%lX", 0xabcdefabL));
EXPECT_STREQ("v", Format("%c", 'v'));
EXPECT_STREQ("wv", Format("%cv", 'w'));
EXPECT_STREQ("A Test", Format("%s", "A Test"));
EXPECT_STREQ("255", Format("%hhu", 0xFFFFUL));
EXPECT_STREQ("a", Format("%tx", &buffer[10] - &buffer[0]));
/* TBD */
EXPECT_STREQ("-2147483647", Format("%ji", (intmax_t)-2147483647L));
}
TEST(sprintf, testOverflow_truncationNotSaturation) {
errno = 0;
EXPECT_STREQ("13398", Format("%hu", 0x123456UL));
EXPECT_EQ(ERANGE, errno);
errno = 0;
EXPECT_STREQ("Test16 65535", Format("%s%hhi %hu", "Test", 10000, 0xFFFFFFFF));
EXPECT_EQ(ERANGE, errno);
}
TEST(sprintf, test_pointer) {
sprintf(buffer, "%p", (void *)0x1234U);
if (sizeof(void *) == 4U) {
EXPECT_STREQ("00001234", buffer);
} else {
EXPECT_STREQ("000000001234", buffer);
}
sprintf(buffer, "%p", (void *)0x12345678U);
if (sizeof(void *) == 4U) {
EXPECT_STREQ("12345678", buffer);
} else {
EXPECT_STREQ("000012345678", buffer);
}
sprintf(buffer, "%p-%p", (void *)0x12345678U, (void *)0x7EDCBA98U);
if (sizeof(void *) == 4U) {
EXPECT_STREQ("12345678-7edcba98", buffer);
} else {
EXPECT_STREQ("000012345678-00007edcba98", buffer);
}
if (sizeof(uintptr_t) == sizeof(uint64_t)) {
sprintf(buffer, "%p", (void *)(uintptr_t)0xFFFFFFFFU);
EXPECT_STREQ("0000ffffffff", buffer);
} else {
sprintf(buffer, "%p", (void *)(uintptr_t)0xFFFFFFFFU);
EXPECT_STREQ("ffffffff", buffer);
}
}
TEST(sprintf, test_unknown_flag) {
EXPECT_STREQ("kmarco", Format("%kmarco", 42, 37));
}
TEST(sprintf, test_buffer_length) {
int ret;
/* EXPECT_EQ(4, snprintf(pushpop(NULL), 10, "%s", "Test")); */
EXPECT_EQ(4, snprintf(pushpop(NULL), 0, "%s", "Test"));
buffer[0] = (char)0xA5;
ret = snprintf(buffer, 0, "%s", "Test");
EXPECT_TRUE(buffer[0] == (char)0xA5);
EXPECT_TRUE(ret == 4);
buffer[0] = (char)0xCC;
snprintf(buffer, 1, "%s", pushpop(&"Test"[0]));
EXPECT_TRUE(buffer[0] == '\0');
snprintf(buffer, 2, "%s", pushpop(&"Hello"[0]));
EXPECT_STREQ("H", buffer);
}
TEST(sprintf, test_ret_value) {
int ret;
ret = snprintf(buffer, 6, "0%s", "1234");
EXPECT_STREQ("01234", buffer);
EXPECT_TRUE(ret == 5);
ret = snprintf(buffer, 6, "0%s", pushpop(&"12345"[0]));
EXPECT_STREQ("01234", buffer);
EXPECT_TRUE(ret == 6); /* '5' is truncated */
ret = snprintf(buffer, 6, "0%s", pushpop(&"1234567"[0]));
EXPECT_STREQ("01234", buffer);
EXPECT_TRUE(ret == 8); /* '567' are truncated */
ret = snprintf(buffer, 10, pushpop(&"hello, world"[0]));
EXPECT_TRUE(ret == 12);
ret = snprintf(buffer, 3, "%d", pushpop(10000));
EXPECT_TRUE(ret == 5);
EXPECT_TRUE(strlen(buffer) == 2U);
EXPECT_TRUE(buffer[0] == '1');
EXPECT_TRUE(buffer[1] == '0');
EXPECT_TRUE(buffer[2] == '\0');
}
TEST(sprintf, test_misc) {
EXPECT_STREQ("53000atest-20 bit",
Format("%u%u%ctest%d %s", 5, 3000, 'a', -20, "bit"));
EXPECT_STREQ("0.33", Format("%.*f", 2, 0.33333333));
EXPECT_STREQ("1", Format("%.*d", -1, 1));
EXPECT_STREQ("foo", Format("%.3s", "foobar"));
EXPECT_STREQ(" ", Format("% .0d", 0));
EXPECT_STREQ(" 00004", Format("%10.5d", 4));
EXPECT_STREQ("hi x", Format("%*sx", -3, "hi"));
}
TEST(sprintf, test_snprintf) {
snprintf(buffer, 100U, "%d", -1000);
EXPECT_STREQ("-1000", buffer);
snprintf(buffer, 3U, "%d", pushpop(-1000));
EXPECT_STREQ("-1", buffer);
}
testonly void vsnprintf_builder_1(char *buf, ...) {
va_list args;
va_start(args, buf);
vsnprintf(buf, 100U, "%d", args);
va_end(args);
}
testonly void vsnprintf_builder_3(char *buf, ...) {
va_list args;
va_start(args, buf);
vsnprintf(buf, 100U, "%d %d %s", args);
va_end(args);
}
TEST(sprintf, test_vsnprintf) {
vsnprintf_builder_1(buffer, -1);
EXPECT_STREQ("-1", buffer);
vsnprintf_builder_3(buffer, 3, -1000, "test");
EXPECT_STREQ("3 -1000 test", buffer);
}
TEST(xasprintf, test) {
void *pp;
ASSERT_STREQ("hello 123", (pp = xasprintf("hello %d", 123)));
free(pp);
}
TEST(xasprintf, pointer_doesntShowNonCanonicalZeroes) {
ASSERT_STREQ("100000000010", gc(xasprintf("%p", 0x0000100000000010)));
ASSERT_STREQ("0x100000000010", gc(xasprintf("%#p", 0x0000100000000010)));
}
TEST(xasprintf, nonCanonicalPointer_discardsHighBits_ratherThanSaturate) {
ASSERT_STREQ("100000000010", gc(xasprintf("%p", 0x1000100000000010)));
ASSERT_STREQ("0x100000000010", gc(xasprintf("%#p", 0x1000100000000010)));
ASSERT_STREQ("7fffffffffff", gc(xasprintf("%p", 0x7fffffffffff)));
ASSERT_STREQ("0x7fffffffffff", gc(xasprintf("%#p", 0x7fffffffffff)));
}
TEST(snprintf, testFixedWidthString_wontOverrunInput) {
const int N = 2;
char *buf = tmalloc(N + 1);
char *inp = memcpy(tmalloc(N), "hi", N);
EXPECT_EQ(2, snprintf(buf, N + 1, "%.*s", N, inp));
EXPECT_BINEQ(u"hi ", buf);
tfree(inp);
tfree(buf);
}
TEST(snprintf, testFixedWidthStringIsNull_wontOverrunBuffer) {
int N = 3;
char *buf = tmalloc(N + 1);
EXPECT_EQ(6, snprintf(buf, N + 1, "%.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"(nu ", buf);
EXPECT_EQ(6, snprintf(buf, N + 1, "%#.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"(nu ", buf);
EXPECT_EQ(4, snprintf(buf, N + 1, "%`.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"NUL ", buf);
EXPECT_EQ(4, snprintf(buf, N + 1, "%`#.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"NUL ", buf);
tfree(buf);
}
TEST(snprintf, testFixedWidthStringIsNull_wontLeakMemory) {
int N = 16;
char *buf = tmalloc(N + 1);
memset(buf, 0, N + 1);
EXPECT_EQ(6, snprintf(buf, N + 1, "%.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"(null)           ", buf);
memset(buf, 0, N + 1);
EXPECT_EQ(6, snprintf(buf, N + 1, "%#.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"(null)           ", buf);
memset(buf, 0, N + 1);
EXPECT_EQ(4, snprintf(buf, N + 1, "%`.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"NULL             ", buf);
memset(buf, 0, N + 1);
EXPECT_EQ(4, snprintf(buf, N + 1, "%`#.*s", pushpop(N), pushpop(NULL)));
EXPECT_BINEQ(u"NULL             ", buf);
tfree(buf);
}