diff --git a/app/tests/float_print_host.c b/app/tests/float_print_host.c deleted file mode 100644 index f736f940..00000000 --- a/app/tests/float_print_host.c +++ /dev/null @@ -1,16 +0,0 @@ -#include - -#define countof(a) (sizeof(a) / sizeof((a)[0])) - -#include "float_test_vec.c" - -int main(void) { - printf("floating point printf tests\n"); - - for (size_t i = 0; i < float_test_vec_size; i++) { - PRINT_FLOAT; - } - - return 0; -} - diff --git a/app/tests/float_test_vec.c b/app/tests/float_test_vec.c deleted file mode 100644 index 6c517867..00000000 --- a/app/tests/float_test_vec.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2014 Travis Geiselbrecht - * - * Use of this source code is governed by a MIT-style - * license that can be found in the LICENSE file or at - * https://opensource.org/licenses/MIT - */ - -#include - -union double_int { - double d; - uint64_t i; -}; - -static const union double_int float_test_vec[] = { - { .d = -2.0 }, - { .d = -1.0 }, - { .d = -0.5 }, - { .d = -0.0 }, - { .d = 0.0 }, - { .d = 0.01 }, - { .d = 0.1 }, - { .d = 0.2 }, - { .d = 0.25 }, - { .d = 0.5 }, - { .d = 0.75 }, - { .d = 1.0 }, - { .d = 2.0 }, - { .d = 3.0 }, - { .d = 10.0 }, - { .d = 100.0 }, - { .d = 123456.0 }, - { .d = -123456.0 }, - { .d = 546.5645644531 }, - { .d = -546.5645644531 }, - { .d = 0.12345 }, - { .d = 0.0000012345 }, - { .d = 0.0000019999 }, - { .d = 0.0000015 }, - { .i = 0x4005bf0a8b145649ULL }, // e - { .i = 0x400921fb54442d18ULL }, // pi - { .i = 0x43f0000000000000ULL }, // 2^64 - { .i = 0x7fefffffffffffffULL }, // largest normalized - { .i = 0x0010000000000000ULL }, // least positive normalized - { .i = 0x0000000000000001ULL }, // smallest possible denorm - { .i = 0x000fffffffffffffULL }, // largest possible denorm - { .i = 0x7ff0000000000001ULL }, // smallest SNAn - { .i = 0x7ff7ffffffffffffULL }, // largest SNAn - { .i = 0x7ff8000000000000ULL }, // smallest QNAn - { .i = 0x7fffffffffffffffULL }, // largest QNAn - { .i = 0xfff0000000000000ULL }, // -infinity - { .i = 0x7ff0000000000000ULL }, // +infinity -}; - -#define countof(a) (sizeof(a) / sizeof((a)[0])) -__attribute__((unused)) static const unsigned int float_test_vec_size = countof(float_test_vec); - -#define PRINT_FLOAT \ - printf("0x%016llx %f %F %a %A\n", \ - float_test_vec[i], \ - *(const double *)&float_test_vec[i], \ - *(const double *)&float_test_vec[i], \ - *(const double *)&float_test_vec[i], \ - *(const double *)&float_test_vec[i]) - diff --git a/app/tests/include/app/tests.h b/app/tests/include/app/tests.h index 7e3890ee..84a9db54 100644 --- a/app/tests/include/app/tests.h +++ b/app/tests/include/app/tests.h @@ -17,8 +17,6 @@ int spinner(int argc, const console_cmd_args *argv); int thread_tests(int argc, const console_cmd_args *argv); int benchmarks(int argc, const console_cmd_args *argv); int clock_tests(int argc, const console_cmd_args *argv); -int printf_tests(int argc, const console_cmd_args *argv); -int printf_tests_float(int argc, const console_cmd_args *argv); int v9p_tests(int argc, const console_cmd_args *argv); int v9fs_tests(int argc, const console_cmd_args *argv); diff --git a/app/tests/printf_tests.c b/app/tests/printf_tests.c deleted file mode 100644 index 1dda9708..00000000 --- a/app/tests/printf_tests.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2008-2014 Travis Geiselbrecht - * - * Use of this source code is governed by a MIT-style - * license that can be found in the LICENSE file or at - * https://opensource.org/licenses/MIT - */ -#include -#include -#include -#include -#include - -// We're doing a few things here that the compiler doesn't like, so disable printf warnings -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat" - -int printf_tests(int argc, const console_cmd_args *argv) { - printf("printf tests\n"); - - printf("numbers:\n"); - printf("int8: %hhd %hhd %hhd\n", -12, 0, 254); - printf("uint8: %hhu %hhu %hhu\n", -12, 0, 254); - printf("int16: %hd %hd %hd\n", -1234, 0, 1234); - printf("uint16:%hu %hu %hu\n", -1234, 0, 1234); - printf("int: %d %d %d\n", -12345678, 0, 12345678); - printf("uint: %u %u %u\n", -12345678, 0, 12345678); - printf("long: %ld %ld %ld\n", -12345678L, 0L, 12345678L); - printf("ulong: %lu %lu %lu\n", -12345678UL, 0UL, 12345678UL); - - printf("longlong: %lli %lli %lli\n", -12345678LL, 0LL, 12345678LL); - printf("ulonglong: %llu %llu %llu\n", -12345678LL, 0LL, 12345678LL); - printf("ssize_t: %zd %zd %zd\n", (ssize_t)-12345678, (ssize_t)0, (ssize_t)12345678); - printf("usize_t: %zu %zu %zu\n", (size_t)-12345678, (size_t)0, (size_t)12345678); - printf("intmax_t: %jd %jd %jd\n", (intmax_t)-12345678, (intmax_t)0, (intmax_t)12345678); - printf("uintmax_t: %ju %ju %ju\n", (uintmax_t)-12345678, (uintmax_t)0, (uintmax_t)12345678); - printf("ptrdiff_t: %td %td %td\n", (ptrdiff_t)-12345678, (ptrdiff_t)0, (ptrdiff_t)12345678); - printf("ptrdiff_t (u): %tu %tu %tu\n", (ptrdiff_t)-12345678, (ptrdiff_t)0, (ptrdiff_t)12345678); - - printf("hex:\n"); - printf("uint8: %hhx %hhx %hhx\n", -12, 0, 254); - printf("uint16:%hx %hx %hx\n", -1234, 0, 1234); - printf("uint: %x %x %x\n", -12345678, 0, 12345678); - printf("ulong: %lx %lx %lx\n", -12345678UL, 0UL, 12345678UL); - printf("ulong: %X %X %X\n", -12345678, 0, 12345678); - printf("ulonglong: %llx %llx %llx\n", -12345678LL, 0LL, 12345678LL); - printf("usize_t: %zx %zx %zx\n", (size_t)-12345678, (size_t)0, (size_t)12345678); - - printf("alt/sign:\n"); - printf("uint: %#x %#X\n", 0xabcdef, 0xabcdef); - printf("int: %+d %+d\n", 12345678, -12345678); - printf("int: % d %+d\n", 12345678, 12345678); - - printf("formatting\n"); - printf("int: a%8da\n", 12345678); - printf("int: a%9da\n", 12345678); - printf("int: a%-9da\n", 12345678); - printf("int: a%10da\n", 12345678); - printf("int: a%-10da\n", 12345678); - printf("int: a%09da\n", 12345678); - printf("int: a%010da\n", 12345678); - printf("int: a%6da\n", 12345678); - - printf("a%1sa\n", "b"); - printf("a%9sa\n", "b"); - printf("a%-9sa\n", "b"); - printf("a%5sa\n", "thisisatest"); - - printf("%03d\n", -2); /* '-02' */ - printf("%0+3d\n", -2); /* '-02' */ - printf("%0+3d\n", 2); /* '+02' */ - printf("%+3d\n", 2); /* ' +2' */ - printf("% 3d\n", -2000); /* '-2000' */ - printf("% 3d\n", 2000); /* ' 2000' */ - printf("%+3d\n", 2000); /* '+2000' */ - printf("%10s\n", "test"); /* ' test' */ - printf("%010s\n", "test"); /* ' test' */ - printf("%-10s\n", "test"); /* 'test ' */ - printf("%-010s\n", "test"); /* 'test ' */ - - int err; - - err = printf("a"); - printf(" returned %d\n", err); - err = printf("ab"); - printf(" returned %d\n", err); - err = printf("abc"); - printf(" returned %d\n", err); - err = printf("abcd"); - printf(" returned %d\n", err); - err = printf("abcde"); - printf(" returned %d\n", err); - err = printf("abcdef"); - printf(" returned %d\n", err); - - /* make sure snprintf terminates at the right spot */ - char buf[32]; - - memset(buf, 0x99, sizeof(buf)); - err = sprintf(buf, "0123456789abcdef012345678"); - printf("sprintf returns %d\n", err); - hexdump8(buf, sizeof(buf)); - - memset(buf, 0x99, sizeof(buf)); - err = snprintf(buf, 15, "0123456789abcdef012345678"); - printf("snprintf returns %d\n", err); - hexdump8(buf, sizeof(buf)); - - memset(buf, 0x99, sizeof(buf)); - err = snprintf(buf, 1, "0123456789abcdef012345678"); - printf("snprintf returns %d\n", err); - hexdump8(buf, sizeof(buf)); - - /* zero length is special case, should not write anything */ - memset(buf, 0x99, sizeof(buf)); - err = snprintf(buf, 0, "0123456789abcdef012345678"); - printf("snprintf returns %d\n", err); - hexdump8(buf, sizeof(buf)); - - /* shold be able to pass null to the output buffer if zero length */ - err = snprintf(NULL, 0, "0123456789abcdef012345678"); - printf("snprintf returns %d\n", err); - - return NO_ERROR; -} - -#include "float_test_vec.c" - -int printf_tests_float(int argc, const console_cmd_args *argv) { - printf("floating point printf tests\n"); - - for (size_t i = 0; i < float_test_vec_size; i++) { - PRINT_FLOAT; - } - - return NO_ERROR; -} - -#pragma GCC diagnostic pop - diff --git a/app/tests/rules.mk b/app/tests/rules.mk index 23008a05..4fd5c4dd 100644 --- a/app/tests/rules.mk +++ b/app/tests/rules.mk @@ -18,8 +18,6 @@ MODULE_FLOAT_SRCS := \ $(LOCAL_DIR)/benchmarks.c \ $(LOCAL_DIR)/float.c \ $(LOCAL_DIR)/float_instructions.S \ - $(LOCAL_DIR)/float_test_vec.c \ - $(LOCAL_DIR)/printf_tests.c \ MODULE_DEPS += \ lib/cbuf diff --git a/app/tests/tests.c b/app/tests/tests.c index 401be1ca..5b50779a 100644 --- a/app/tests/tests.c +++ b/app/tests/tests.c @@ -13,8 +13,6 @@ #include STATIC_COMMAND_START -STATIC_COMMAND("printf_tests", "test printf", &printf_tests) -STATIC_COMMAND("printf_tests_float", "test printf with floating point", &printf_tests_float) STATIC_COMMAND("thread_tests", "test the scheduler", &thread_tests) STATIC_COMMAND("port_tests", "test the ports", &port_tests) STATIC_COMMAND("clock_tests", "test clocks", &clock_tests) diff --git a/lib/libc/test/printf_tests.cpp b/lib/libc/test/printf_tests.cpp index 094c59cf..2a0e0c73 100644 --- a/lib/libc/test/printf_tests.cpp +++ b/lib/libc/test/printf_tests.cpp @@ -25,7 +25,7 @@ bool test_printf(const char* expected, const char* format, ...) { int length = vsnprintf(buf, sizeof(buf), format, args); va_end(args); - if (length < 0 || length >= (int)sizeof(buf)) { + if (length < 0 || length >= static_cast(sizeof(buf))) { printf("vsnprintf() returned %d\n", length); return false; } @@ -35,7 +35,7 @@ bool test_printf(const char* expected, const char* format, ...) { printf("missing string terminator\n"); success = false; } - if (length != (int)strlen(expected) || memcmp(buf, expected, length + 1) != 0) { + if (length != static_cast(strlen(expected)) || memcmp(buf, expected, length + 1) != 0) { printf("expected: \"%s\" (length %zu)\n", expected, strlen(expected)); printf("but got: \"%s\" (length %zu) with return value %d)\n", buf, strlen(buf), length); success = false; @@ -496,8 +496,6 @@ bool snprintf_truncation_test_null_buffer() { END_TEST; } -} // namespace - BEGIN_TEST_CASE(printf_tests) RUN_TEST(numbers) RUN_TEST(hex) @@ -508,3 +506,5 @@ RUN_TEST(snprintf_truncation_test) RUN_TEST(snprintf_truncation_test_zero_length) RUN_TEST(snprintf_truncation_test_null_buffer) END_TEST_CASE(printf_tests) + +} // namespace diff --git a/lib/libc/test/printf_tests_float.cpp b/lib/libc/test/printf_tests_float.cpp new file mode 100644 index 00000000..90d71faa --- /dev/null +++ b/lib/libc/test/printf_tests_float.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2008-2014 Travis Geiselbrecht +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT + +#include +#include +#include + +#include "printf_tests_float_vec.h" + +namespace { + +bool test_printf(const char* expected, const char* format, ...) { + char buf[100]; + va_list args; + va_start(args, format); + int length = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + if (length < 0 || length >= static_cast(sizeof(buf))) { + printf("vsnprintf() returned %d\n", length); + return false; + } + + bool success = true; + if (buf[length] != '\0') { + printf("missing string terminator\n"); + success = false; + } + if (length != static_cast(strlen(expected)) || memcmp(buf, expected, length + 1) != 0) { + printf("expected: \"%s\" (length %zu)\n", expected, strlen(expected)); + printf("but got: \"%s\" (length %zu) with return value %d)\n", buf, strlen(buf), length); + success = false; + } + return success; +} + +bool basic() { + BEGIN_TEST; + + for (const auto &vec : float_test_vec) { + EXPECT_TRUE(test_printf(vec.expected_f, "%f", vec.d)); + EXPECT_TRUE(test_printf(vec.expected_F, "%F", vec.d)); + } + END_TEST; +} + +bool hex() { + BEGIN_TEST; + + for (const auto &vec : float_test_vec) { + EXPECT_TRUE(test_printf(vec.expected_a, "%a", vec.d)); + EXPECT_TRUE(test_printf(vec.expected_A, "%A", vec.d)); + } + END_TEST; +} + +BEGIN_TEST_CASE(printf_tests_float) +RUN_TEST(basic); +RUN_TEST(hex); +END_TEST_CASE(printf_tests_float) + +} // namespace diff --git a/lib/libc/test/printf_tests_float_host.cpp b/lib/libc/test/printf_tests_float_host.cpp new file mode 100644 index 00000000..58c263e8 --- /dev/null +++ b/lib/libc/test/printf_tests_float_host.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ + +#include +#include + +#include "printf_tests_float_vec.h" + +// Host program that will print the floating point test vector for manual comparison. + +int main(int argc, char **argv) { + printf("floating point printf tests\n"); + + for (const auto &vec : float_test_vec) { + printf("%" PRIx64 " %f %F %a %A\n", \ + vec.i, \ + vec.d, \ + vec.d, \ + vec.d, \ + vec.d); + } + + return 0; +} + diff --git a/lib/libc/test/printf_tests_float_vec.h b/lib/libc/test/printf_tests_float_vec.h new file mode 100644 index 00000000..cbe7dad6 --- /dev/null +++ b/lib/libc/test/printf_tests_float_vec.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#pragma once + +#include + +struct float_test_vec_t { + union { + double d; + uint64_t i; + }; + const char *expected_f; + const char *expected_F; + const char *expected_a; + const char *expected_A; +}; + +const struct float_test_vec_t float_test_vec[] = { + { .i = 0xc000000000000000, .expected_f="-2.000000", .expected_F="-2.000000", .expected_a="-0x1p+1", .expected_A="-0X1P+1" }, + { .i = 0xbff0000000000000, .expected_f="-1.000000", .expected_F="-1.000000", .expected_a="-0x1p+0", .expected_A="-0X1P+0" }, + { .i = 0xbfe0000000000000, .expected_f="-0.500000", .expected_F="-0.500000", .expected_a="-0x1p-1", .expected_A="-0X1P-1" }, + { .i = 0x8000000000000000, .expected_f="-0.000000", .expected_F="-0.000000", .expected_a="-0x0p+0", .expected_A="-0X0P+0" }, + { .i = 0x0000000000000000, .expected_f="0.000000", .expected_F="0.000000", .expected_a="0x0p+0", .expected_A="0X0P+0" }, + { .i = 0x3f847ae147ae147b, .expected_f="0.010000", .expected_F="0.010000", .expected_a="0x1.47ae147ae147bp-7", .expected_A="0X1.47AE147AE147BP-7" }, + { .i = 0x3fb999999999999a, .expected_f="0.100000", .expected_F="0.100000", .expected_a="0x1.999999999999ap-4", .expected_A="0X1.999999999999AP-4" }, + { .i = 0x3fc999999999999a, .expected_f="0.200000", .expected_F="0.200000", .expected_a="0x1.999999999999ap-3", .expected_A="0X1.999999999999AP-3" }, + { .i = 0x3fd0000000000000, .expected_f="0.250000", .expected_F="0.250000", .expected_a="0x1p-2", .expected_A="0X1P-2" }, + { .i = 0x3fe0000000000000, .expected_f="0.500000", .expected_F="0.500000", .expected_a="0x1p-1", .expected_A="0X1P-1" }, + { .i = 0x3fe8000000000000, .expected_f="0.750000", .expected_F="0.750000", .expected_a="0x1.8p-1", .expected_A="0X1.8P-1" }, + { .i = 0x3ff0000000000000, .expected_f="1.000000", .expected_F="1.000000", .expected_a="0x1p+0", .expected_A="0X1P+0" }, + { .i = 0x4000000000000000, .expected_f="2.000000", .expected_F="2.000000", .expected_a="0x1p+1", .expected_A="0X1P+1" }, + { .i = 0x4008000000000000, .expected_f="3.000000", .expected_F="3.000000", .expected_a="0x1.8p+1", .expected_A="0X1.8P+1" }, + { .i = 0x4024000000000000, .expected_f="10.000000", .expected_F="10.000000", .expected_a="0x1.4p+3", .expected_A="0X1.4P+3" }, + { .i = 0x4059000000000000, .expected_f="100.000000", .expected_F="100.000000", .expected_a="0x1.9p+6", .expected_A="0X1.9P+6" }, + { .i = 0x40fe240000000000, .expected_f="123456.000000", .expected_F="123456.000000", .expected_a="0x1.e24p+16", .expected_A="0X1.E24P+16" }, + { .i = 0xc0fe240000000000, .expected_f="-123456.000000", .expected_F="-123456.000000", .expected_a="-0x1.e24p+16", .expected_A="-0X1.E24P+16" }, + { .i = 0x408114843a5e3464, .expected_f="546.564564", .expected_F="546.564564", .expected_a="0x1.114843a5e3464p+9", .expected_A="0X1.114843A5E3464P+9" }, + { .i = 0xc08114843a5e3464, .expected_f="-546.564564", .expected_F="-546.564564", .expected_a="-0x1.114843a5e3464p+9", .expected_A="-0X1.114843A5E3464P+9" }, + { .i = 0x3fbf9a6b50b0f27c, .expected_f="0.123450", .expected_F="0.123450", .expected_a="0x1.f9a6b50b0f27cp-4", .expected_A="0X1.F9A6B50B0F27CP-4" }, + { .i = 0x3eb4b6231abfd271, .expected_f="0.000001", .expected_F="0.000001", .expected_a="0x1.4b6231abfd271p-20", .expected_A="0X1.4B6231ABFD271P-20" }, + { .i = 0x3ec0c6c0a6f639de, .expected_f="0.000002", .expected_F="0.000002", .expected_a="0x1.0c6c0a6f639dep-19", .expected_A="0X1.0C6C0A6F639DEP-19" }, + { .i = 0x3eb92a737110e454, .expected_f="0.000002", .expected_F="0.000002", .expected_a="0x1.92a737110e454p-20", .expected_A="0X1.92A737110E454P-20" }, + { .i = 0x4005bf0a8b145649, .expected_f="2.718282", .expected_F="2.718282", .expected_a="0x1.5bf0a8b145649p+1", .expected_A="0X1.5BF0A8B145649P+1" }, + { .i = 0x400921fb54442d18, .expected_f="3.141593", .expected_F="3.141593", .expected_a="0x1.921fb54442d18p+1", .expected_A="0X1.921FB54442D18P+1" }, + { .i = 0x43f0000000000000, .expected_f="", .expected_F="", .expected_a="0x1p+64", .expected_A="0X1P+64" }, + { .i = 0x7fefffffffffffff, .expected_f="", .expected_F="", .expected_a="0x1.fffffffffffffp+1023", .expected_A="0X1.FFFFFFFFFFFFFP+1023" }, + { .i = 0x0010000000000000, .expected_f="", .expected_F="", .expected_a="0x1p-1022", .expected_A="0X1P-1022" }, + { .i = 0x0000000000000001, .expected_f="den", .expected_F="DEN", .expected_a="den", .expected_A="DEN" }, + { .i = 0x000fffffffffffff, .expected_f="den", .expected_F="DEN", .expected_a="den", .expected_A="DEN" }, + { .i = 0x7ff0000000000001, .expected_f="nan", .expected_F="NAN", .expected_a="nan", .expected_A="NAN" }, + { .i = 0x7ff7ffffffffffff, .expected_f="nan", .expected_F="NAN", .expected_a="nan", .expected_A="NAN" }, + { .i = 0x7ff8000000000000, .expected_f="nan", .expected_F="NAN", .expected_a="nan", .expected_A="NAN" }, + { .i = 0x7fffffffffffffff, .expected_f="nan", .expected_F="NAN", .expected_a="nan", .expected_A="NAN" }, + { .i = 0xfff0000000000000, .expected_f="-inf", .expected_F="-INF", .expected_a="-inf", .expected_A="-INF" }, + { .i = 0x7ff0000000000000, .expected_f="inf", .expected_F="INF", .expected_a="inf", .expected_A="INF" }, +}; diff --git a/lib/libc/test/rules.mk b/lib/libc/test/rules.mk index bc8c1693..b83bb68b 100644 --- a/lib/libc/test/rules.mk +++ b/lib/libc/test/rules.mk @@ -3,6 +3,7 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) MODULE_SRCS += $(LOCAL_DIR)/printf_tests.cpp +MODULE_FLOAT_SRCS += $(LOCAL_DIR)/printf_tests_float.cpp MODULE_DEPS += lib/libc MODULE_DEPS += lib/unittest