zephyr/tests/unit/cbprintf/main.c
Daniel Leung aff6e8b2f7 lib: os: cbprint: enable tagged arguments for packaging
This adds some bits to support tagged arguments to be used for
packaging. If enabled, the packaging function no longer looks at
the format strings to determine the types of arguments, but
instead, each argument is tagged with a type by preceding it
with another argument as type (integer). This allows the format
strings to be removed from the final binary to conserve space.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2022-06-08 00:15:55 +09:00

1477 lines
35 KiB
C

/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#define CONFIG_CBPRINTF_LIBC_SUBSTS 1
#include <ztest.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <wctype.h>
#include <stddef.h>
#include <string.h>
#include <zephyr/sys/util.h>
#define CBPRINTF_VIA_UNIT_TEST
/* Unit testing doesn't use Kconfig, so if we're not building from
* twister force selection of all features. If we are use flags to
* determine which features are desired. Yes, this is a mess.
*/
#ifndef VIA_TWISTER
/* Set this to truthy to use libc's snprintf as external validation.
* This should be used with all options enabled.
*/
#define USE_LIBC 0
#define USE_PACKAGED 0
#define CONFIG_CBPRINTF_COMPLETE 1
#define CONFIG_CBPRINTF_FULL_INTEGRAL 1
#define CONFIG_CBPRINTF_FP_SUPPORT 1
#define CONFIG_CBPRINTF_FP_A_SUPPORT 1
#define CONFIG_CBPRINTF_N_SPECIFIER 1
#define CONFIG_CBPRINTF_LIBC_SUBSTS 1
/* compensate for selects */
#if (CONFIG_CBPRINTF_FP_A_SUPPORT - 0)
#undef CONFIG_CBPRINTF_REDUCED_INTEGRAL
#undef CONFIG_CBPRINTF_FULL_INTEGRAL
#undef CONFIG_CBPRINTF_FP_SUPPORT
#define CONFIG_CBPRINTF_FULL_INTEGRAL 1
#define CONFIG_CBPRINTF_FP_SUPPORT 1
#endif
#if !(CONFIG_CBPRINTF_FP_SUPPORT - 0)
#undef CONFIG_CBPRINTF_FP_SUPPORT
#endif
/* Convert choice selections to one defined flag */
#if !(CONFIG_CBPRINTF_COMPLETE - 0)
#ifdef CONFIG_CBPRINTF_FP_SUPPORT
#error Inconsistent configuration
#endif
#undef CONFIG_CBPRINTF_COMPLETE
#define CONFIG_CBPRINTF_NANO 1
#endif
#if !(CONFIG_CBPRINTF_FULL_INTEGRAL - 0)
#undef CONFIG_CBPRINTF_FULL_INTEGRAL
#define CONFIG_CBPRINTF_REDUCED_INTEGRAL 1
#endif
#else /* VIA_TWISTER */
#if (VIA_TWISTER & 0x01) != 0
#define CONFIG_CBPRINTF_FULL_INTEGRAL 1
#else
#define CONFIG_CBPRINTF_REDUCED_INTEGRAL 1
#endif
#if (VIA_TWISTER & 0x02) != 0
#define CONFIG_CBPRINTF_FP_SUPPORT 1
#endif
#if (VIA_TWISTER & 0x04) != 0
#define CONFIG_CBPRINTF_FP_A_SUPPORT 1
#endif
#if (VIA_TWISTER & 0x08) != 0
#define CONFIG_CBPRINTF_N_SPECIFIER 1
#endif
#if (VIA_TWISTER & 0x40) != 0
#define CONFIG_CBPRINTF_FP_ALWAYS_A 1
#endif
#if (VIA_TWISTER & 0x80) != 0
#define CONFIG_CBPRINTF_NANO 1
#else /* 0x80 */
#define CONFIG_CBPRINTF_COMPLETE 1
#endif /* 0x80 */
#if (VIA_TWISTER & 0x100) != 0
#define CONFIG_CBPRINTF_LIBC_SUBSTS 1
#endif
#if (VIA_TWISTER & 0x200) != 0
#define USE_PACKAGED 1
#else
#define USE_PACKAGED 0
#endif
#if (VIA_TWISTER & 0x400) != 0
#define CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE 1
#endif
#if (VIA_TWISTER & 0x800) != 0
#define AVOID_C_GENERIC 1
#endif
#if (VIA_TWISTER & 0x1000) != 0
#define PKG_ALIGN_OFFSET sizeof(void *)
#endif
#if (VIA_TWISTER & 0x2000) != 0
#define PACKAGE_FLAGS CBPRINTF_PACKAGE_ADD_STRING_IDXS
#endif
#endif /* VIA_TWISTER */
/* Can't use IS_ENABLED on symbols that don't start with CONFIG_
* without checkpatch complaints, so do something else.
*/
#if USE_LIBC
#define ENABLED_USE_LIBC true
#else
#define ENABLED_USE_LIBC false
#endif
#if USE_PACKAGED
#define ENABLED_USE_PACKAGED true
#else
#define ENABLED_USE_PACKAGED false
#endif
#if AVOID_C_GENERIC
#define Z_C_GENERIC 0
#endif
#ifndef PACKAGE_FLAGS
#define PACKAGE_FLAGS 0
#endif
#include <zephyr/sys/cbprintf.h>
#include "../../../lib/os/cbprintf.c"
#if defined(CONFIG_CBPRINTF_COMPLETE)
#include "../../../lib/os/cbprintf_complete.c"
#elif defined(CONFIG_CBPRINTF_NANO)
#include "../../../lib/os/cbprintf_nano.c"
#endif
#if USE_PACKAGED
#include "../../../lib/os/cbprintf_packaged.c"
#endif
#ifndef PKG_ALIGN_OFFSET
#define PKG_ALIGN_OFFSET (size_t)0
#endif
/* We can't determine at build-time whether int is 64-bit, so assume
* it is. If not the values are truncated at build time, and the str
* pointers will be updated during test initialization.
*/
static const unsigned int pfx_val = (unsigned int)0x7b6b5b4b3b2b1b0b;
static const char pfx_str64[] = "7b6b5b4b3b2b1b0b";
static const char *pfx_str = pfx_str64;
static const unsigned int sfx_val = (unsigned int)0xe7e6e5e4e3e2e1e0;
static const char sfx_str64[] = "e7e6e5e4e3e2e1e0";
static const char *sfx_str = sfx_str64;
/* Buffer adequate to hold packaged state for all tested
* configurations.
*/
#if USE_PACKAGED
static uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) packaged[256];
#endif
#define WRAP_FMT(_fmt) "%x" _fmt "%x"
#define PASS_ARG(...) pfx_val, __VA_ARGS__, sfx_val
static inline int match_str(const char **strp,
const char *expected,
size_t len)
{
const char *str = *strp;
int rv = strncmp(str, expected, len);
*strp += len;
return rv;
}
static inline int match_pfx(const char **ptr)
{
return match_str(ptr, pfx_str, 2U * sizeof(pfx_val));
}
static inline int match_sfx(const char **ptr)
{
return match_str(ptr, sfx_str, 2U * sizeof(sfx_val));
}
/* This has to be more than 255 so we can test over-sized widths. */
static char buf[512];
struct out_buffer {
char *buf;
size_t idx;
size_t size;
};
static struct out_buffer outbuf;
static inline void reset_out(void)
{
outbuf.buf = buf;
outbuf.size = ARRAY_SIZE(buf);
outbuf.idx = 0;
}
static void outbuf_null_terminate(struct out_buffer *outbuf)
{
int idx = outbuf->idx - ((outbuf->idx == outbuf->size) ? 1 : 0);
outbuf->buf[idx] = 0;
}
static int out(int c, void *dest)
{
int rv = EOF;
struct out_buffer *buf = dest;
if (buf->idx < buf->size) {
buf->buf[buf->idx++] = (char)(unsigned char)c;
rv = (int)(unsigned char)c;
}
return rv;
}
__printf_like(2, 3)
static int prf(char *static_package_str, const char *format, ...)
{
va_list ap;
int rv;
reset_out();
va_start(ap, format);
#if USE_LIBC
rv = vsnprintf(buf, sizeof(buf), format, ap);
#else
#if USE_PACKAGED
rv = cbvprintf_package(packaged, sizeof(packaged), PACKAGE_FLAGS, format, ap);
if (rv >= 0) {
rv = cbpprintf(out, &outbuf, packaged);
if (rv == 0 && static_package_str) {
rv = strcmp(static_package_str, outbuf.buf);
}
}
#else
rv = cbvprintf(out, &outbuf, format, ap);
#endif
outbuf_null_terminate(&outbuf);
#endif
va_end(ap);
return rv;
}
static int rawprf(const char *format, ...)
{
va_list ap;
int rv;
va_start(ap, format);
#if USE_PACKAGED
va_list ap2;
int len;
uint8_t *pkg_buf = &packaged[PKG_ALIGN_OFFSET];
va_copy(ap2, ap);
len = cbvprintf_package(NULL, PKG_ALIGN_OFFSET, PACKAGE_FLAGS, format, ap2);
va_end(ap2);
if (len >= 0) {
rv = cbvprintf_package(pkg_buf, len, PACKAGE_FLAGS, format, ap);
} else {
rv = len;
}
if (rv >= 0) {
rv = cbpprintf(out, &outbuf, pkg_buf);
}
#else
rv = cbvprintf(out, &outbuf, format, ap);
#endif
va_end(ap);
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)
&& !IS_ENABLED(CONFIG_CBPRINTF_LIBC_SUBSTS)) {
zassert_equal(rv, 0, NULL);
rv = outbuf.idx;
}
return rv;
}
#define TEST_PRF2(rc, _fmt, ...) do { \
char _buf[512]; \
char *sp_buf = NULL; /* static package buffer */\
if (USE_PACKAGED && !CBPRINTF_MUST_RUNTIME_PACKAGE(0, 0, _fmt, __VA_ARGS__)) { \
int rv = 0; \
size_t _len; \
struct out_buffer package_buf = { \
.buf = _buf, .size = ARRAY_SIZE(_buf), .idx = 0 \
}; \
CBPRINTF_STATIC_PACKAGE(NULL, 0, _len, PKG_ALIGN_OFFSET, \
PACKAGE_FLAGS, _fmt, __VA_ARGS__); \
uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) \
package[_len + PKG_ALIGN_OFFSET]; \
int st_pkg_rv; \
CBPRINTF_STATIC_PACKAGE(&package[PKG_ALIGN_OFFSET], _len - 1, \
st_pkg_rv, PKG_ALIGN_OFFSET, \
PACKAGE_FLAGS, _fmt, __VA_ARGS__); \
zassert_equal(st_pkg_rv, -ENOSPC, NULL); \
CBPRINTF_STATIC_PACKAGE(&package[PKG_ALIGN_OFFSET], _len, \
st_pkg_rv, PKG_ALIGN_OFFSET, \
PACKAGE_FLAGS, _fmt, __VA_ARGS__); \
zassert_equal(st_pkg_rv, _len, NULL); \
rv = cbpprintf(out, &package_buf, &package[PKG_ALIGN_OFFSET]); \
if (rv >= 0) { \
sp_buf = _buf; \
} \
} \
*rc = prf(sp_buf, _fmt, __VA_ARGS__); \
} while (0)
#define TEST_PRF(rc, _fmt, ...) \
TEST_PRF2(rc, WRAP_FMT(_fmt), PASS_ARG(__VA_ARGS__))
#ifdef CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE
#define TEST_PRF_LONG_DOUBLE(rc, _fmt, ...) \
TEST_PRF(rc, _fmt, __VA_ARGS__)
#else
/* Skip testing of static packaging if long double support not enabled. */
#define TEST_PRF_LONG_DOUBLE(rc, _fmt, ...) \
*rc = prf(NULL, WRAP_FMT(_fmt), PASS_ARG(__VA_ARGS__))
#endif
struct context {
const char *expected;
const char *got;
const char *file;
unsigned int line;
};
__printf_like(3, 4)
static bool prf_failed(const struct context *ctx,
const char *cp,
const char *format,
...)
{
va_list ap;
va_start(ap, format);
printf("%s:%u for '%s'\n", ctx->file, ctx->line, ctx->expected);
printf("in: %s\nat: %*c%s\n", ctx->got,
(unsigned int)(cp - ctx->got), '>', ctx->expected);
vprintf(format, ap);
va_end(ap);
return false;
}
static inline bool prf_check(const char *expected,
int rv,
const char *file,
unsigned int line)
{
const struct context ctx = {
.expected = expected,
.got = buf,
.file = file,
.line = line,
};
const char *str = buf;
const char *sp;
int rc;
sp = str;
rc = match_pfx(&str);
if (rc != 0) {
return prf_failed(&ctx, sp, "pfx mismatch %d\n", rc);
}
sp = str;
rc = match_str(&str, expected, strlen(expected));
if (rc != 0) {
return prf_failed(&ctx, sp, "str mismatch %d\n", rc);
}
sp = str;
rc = match_sfx(&str);
if (rc != 0) {
return prf_failed(&ctx, sp, "sfx mismatch, %d\n", rc);
}
rc = (*str != 0);
if (rc != 0) {
return prf_failed(&ctx, str, "no eos %02x\n", *str);
}
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)
&& !IS_ENABLED(CONFIG_CBPRINTF_LIBC_SUBSTS)) {
if (rv != 0) {
return prf_failed(&ctx, str, "nano rv %d != 0\n", rc);
}
} else {
int len = (int)(str - buf);
if (rv != len) {
return prf_failed(&ctx, str, "rv %d != expected %d\n",
rv, len);
}
}
return true;
}
#define PRF_CHECK(expected, rv) \
zassert_true(prf_check(expected, rv, __FILE__, __LINE__), \
NULL)
static void test_pct(void)
{
int rc;
TEST_PRF(&rc, "/%%/%c/", 'a');
PRF_CHECK("/%/a/", rc);
}
static void test_c(void)
{
int rc;
TEST_PRF(&rc, "%c", 'a');
PRF_CHECK("a", rc);
rc = prf(NULL, "/%256c/", 'a');
const char *bp = buf;
size_t spaces = 255;
zassert_equal(rc, 258, "len %d", rc);
zassert_equal(*bp, '/', NULL);
++bp;
while (spaces-- > 0) {
zassert_equal(*bp, ' ', NULL);
++bp;
}
zassert_equal(*bp, 'a', NULL);
++bp;
zassert_equal(*bp, '/', NULL);
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("short test for nano\n");
return;
}
TEST_PRF(&rc, "%lc", (wint_t)'a');
if (ENABLED_USE_LIBC) {
PRF_CHECK("a", rc);
} else {
PRF_CHECK("%lc", rc);
}
}
static void test_s(void)
{
const char *s = "123";
static wchar_t ws[] = L"abc";
int rc;
TEST_PRF(&rc, "/%s/", s);
PRF_CHECK("/123/", rc);
TEST_PRF(&rc, "/%6s/%-6s/%2s/", s, s, s);
PRF_CHECK("/ 123/123 /123/", rc);
TEST_PRF(&rc, "/%.6s/%.2s/%.s/", s, s, s);
PRF_CHECK("/123/12//", rc);
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("short test for nano\n");
return;
}
TEST_PRF(&rc, "%ls", ws);
if (ENABLED_USE_LIBC) {
PRF_CHECK("abc", rc);
} else {
PRF_CHECK("%ls", rc);
}
}
static void test_v_c(void)
{
int rc;
reset_out();
buf[1] = 'b';
rc = rawprf("%c", 'a');
zassert_equal(rc, 1, NULL);
zassert_equal(buf[0], 'a', NULL);
if (!ENABLED_USE_LIBC) {
zassert_equal(buf[1], 'b', "wth %x", buf[1]);
}
}
static void test_d_length(void)
{
int min = -1234567890;
int max = 1876543210;
long long svll = 123LL << 48;
long long svll2 = -2LL;
unsigned long long uvll = 4000000000LLU;
int rc;
TEST_PRF(&rc, "%d/%d", min, max);
PRF_CHECK("-1234567890/1876543210", rc);
TEST_PRF(&rc, "%u/%u", min, max);
PRF_CHECK("3060399406/1876543210", rc);
if (!IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TEST_PRF(&rc, "%hd/%hd", min, max);
PRF_CHECK("-722/-14614", rc);
TEST_PRF(&rc, "%hhd/%hhd", min, max);
PRF_CHECK("46/-22", rc);
}
TEST_PRF(&rc, "%ld/%ld/%lu/", (long)min, (long)max, 4000000000UL);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)
|| (sizeof(long) <= 4)
|| IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
PRF_CHECK("-1234567890/1876543210/4000000000/", rc);
} else {
PRF_CHECK("%ld/%ld/%lu/", rc);
}
TEST_PRF(&rc, "/%lld/%lld/%lld/%llu/", svll, -svll, svll2, uvll);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)) {
PRF_CHECK("/34621422135410688/-34621422135410688/-2/4000000000/", rc);
} else if (IS_ENABLED(CONFIG_CBPRINTF_COMPLETE)) {
PRF_CHECK("/%lld/%lld/%lld/%llu/", rc);
} else if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
PRF_CHECK("/ERR/ERR/-2/4000000000/", rc);
} else {
zassert_true(false, "Missed case!");
}
TEST_PRF(&rc, "%lld/%lld", (long long)min, (long long)max);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)) {
PRF_CHECK("-1234567890/1876543210", rc);
} else if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
PRF_CHECK("-1234567890/1876543210", rc);
} else {
PRF_CHECK("%lld/%lld", rc);
}
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("short test for nano\n");
return;
}
TEST_PRF(&rc, "%jd/%jd", (intmax_t)min, (intmax_t)max);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)) {
PRF_CHECK("-1234567890/1876543210", rc);
} else {
PRF_CHECK("%jd/%jd", rc);
}
TEST_PRF(&rc, "%zd/%td/%td", (size_t)min, (ptrdiff_t)min,
(ptrdiff_t)max);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)
|| (sizeof(size_t) <= 4)) {
PRF_CHECK("-1234567890/-1234567890/1876543210", rc);
} else {
PRF_CHECK("%zd/%td/%td", rc);
}
/* These have to be tested without the format validation
* attribute because they produce diagnostics, but we have
* intended behavior so we have to test them.
*/
reset_out();
rc = rawprf("/%Ld/", max);
zassert_equal(rc, 5, "len %d", rc);
zassert_equal(strncmp("/%Ld/", buf, rc), 0, NULL);
}
static void test_d_flags(void)
{
int sv = 123;
int rc;
/* Stuff related to sign */
TEST_PRF(&rc, "/%d/%-d/%+d/% d/",
sv, sv, sv, sv);
PRF_CHECK("/123/123/+123/ 123/", rc);
/* Stuff related to width padding */
TEST_PRF(&rc, "/%1d/%4d/%-4d/%04d/%15d/%-15d/",
sv, sv, sv, sv, sv, sv);
PRF_CHECK("/123/ 123/123 /0123/"
" 123/123 /", rc);
/* Stuff related to precision */
TEST_PRF(&rc, "/%.6d/%6.4d/", sv, sv);
PRF_CHECK("/000123/ 0123/", rc);
/* Now with negative values */
sv = -sv;
TEST_PRF(&rc, "/%d/%-d/%+d/% d/",
sv, sv, sv, sv);
PRF_CHECK("/-123/-123/-123/-123/", rc);
TEST_PRF(&rc, "/%1d/%6d/%-6d/%06d/%13d/%-13d/",
sv, sv, sv, sv, sv, sv);
PRF_CHECK("/-123/ -123/-123 /-00123/"
" -123/-123 /", rc);
TEST_PRF(&rc, "/%.6d/%6.4d/", sv, sv);
PRF_CHECK("/-000123/ -0123/", rc);
/* These have to be tested without the format validation
* attribute because they produce diagnostics, but the
* standard specifies behavior so we have to test them.
*/
sv = 123;
reset_out();
rc = rawprf("/%#d/% +d/%-04d/%06.4d/", sv, sv, sv, sv);
zassert_equal(rc, 22, "rc %d", rc);
zassert_equal(strncmp("/123/+123/123 / 0123/",
buf, rc), 0, NULL);
}
static void test_x_length(void)
{
unsigned int min = 0x4c3c2c1c;
unsigned int max = 0x4d3d2d1d;
int rc;
TEST_PRF(&rc, "%x/%X", min, max);
PRF_CHECK("4c3c2c1c/4D3D2D1D", rc);
TEST_PRF(&rc, "%lx/%lX", (unsigned long)min, (unsigned long)max);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)
|| (sizeof(long) <= 4)
|| IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
PRF_CHECK("4c3c2c1c/4D3D2D1D", rc);
} else {
PRF_CHECK("%lx/%lX", rc);
}
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("short test for nano\n");
return;
}
TEST_PRF(&rc, "%hx/%hX", min, max);
PRF_CHECK("2c1c/2D1D", rc);
TEST_PRF(&rc, "%hhx/%hhX", min, max);
PRF_CHECK("1c/1D", rc);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)) {
TEST_PRF(&rc, "%llx/%llX", (unsigned long long)min,
(unsigned long long)max);
PRF_CHECK("4c3c2c1c/4D3D2D1D", rc);
TEST_PRF(&rc, "%jx/%jX", (uintmax_t)min, (uintmax_t)max);
PRF_CHECK("4c3c2c1c/4D3D2D1D", rc);
}
TEST_PRF(&rc, "%zx/%zX", (size_t)min, (size_t)max);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)
|| (sizeof(size_t) <= 4)) {
PRF_CHECK("4c3c2c1c/4D3D2D1D", rc);
} else {
PRF_CHECK("%zx/%zX", rc);
}
TEST_PRF(&rc, "%tx/%tX", (ptrdiff_t)min, (ptrdiff_t)max);
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)
|| (sizeof(ptrdiff_t) <= 4)) {
PRF_CHECK("4c3c2c1c/4D3D2D1D", rc);
} else {
PRF_CHECK("%tx/%tX", rc);
}
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)
&& (sizeof(long long) > sizeof(int))) {
unsigned long long min = 0x8c7c6c5c4c3c2c1cULL;
unsigned long long max = 0x8d7d6d5d4d3d2d1dULL;
TEST_PRF(&rc, "%llx/%llX", (unsigned long long)min,
(unsigned long long)max);
PRF_CHECK("8c7c6c5c4c3c2c1c/8D7D6D5D4D3D2D1D", rc);
}
}
static void test_x_flags(void)
{
unsigned int sv = 0x123;
int rc;
/* Stuff related to sign flags, which have no effect on
* unsigned conversions, and alternate form
*/
TEST_PRF(&rc, "/%x/%-x/%#x/",
sv, sv, sv);
PRF_CHECK("/123/123/0x123/", rc);
/* Stuff related to width and padding */
TEST_PRF(&rc, "/%1x/%4x/%-4x/%04x/%#15x/%-15x/",
sv, sv, sv, sv, sv, sv);
PRF_CHECK("/123/ 123/123 /0123/"
" 0x123/123 /", rc);
/* These have to be tested without the format validation
* attribute because they produce diagnostics, but the
* standard specifies behavior so we have to test them.
*/
reset_out();
rc = rawprf("/%+x/% x/", sv, sv);
zassert_equal(rc, 9, "rc %d", rc);
zassert_equal(strncmp("/123/123/", buf, rc), 0, NULL);
}
static void test_o(void)
{
unsigned int v = 01234567;
int rc;
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("skipped test for nano\n");
return;
}
TEST_PRF(&rc, "%o", v);
PRF_CHECK("1234567", rc);
TEST_PRF(&rc, "%#o", v);
PRF_CHECK("01234567", rc);
}
static void test_fp_value(void)
{
if (!IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
TC_PRINT("skipping unsupported feature\n");
return;
}
double dv = 1234.567;
int rc;
TEST_PRF(&rc, "/%f/%F/", dv, dv);
PRF_CHECK("/1234.567000/1234.567000/", rc);
TEST_PRF(&rc, "%g", dv);
PRF_CHECK("1234.57", rc);
TEST_PRF(&rc, "%e", dv);
PRF_CHECK("1.234567e+03", rc);
TEST_PRF(&rc, "%E", dv);
PRF_CHECK("1.234567E+03", rc);
TEST_PRF(&rc, "%a", dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
PRF_CHECK("0x1.34a449ba5e354p+10", rc);
} else {
PRF_CHECK("%a", rc);
}
dv = 1E3;
TEST_PRF(&rc, "%.2f", dv);
PRF_CHECK("1000.00", rc);
dv = 1E20;
TEST_PRF(&rc, "%.0f", dv);
PRF_CHECK("100000000000000000000", rc);
TEST_PRF(&rc, "%.20e", dv);
PRF_CHECK("1.00000000000000000000e+20", rc);
dv = 1E-3;
TEST_PRF(&rc, "%.3e", dv);
PRF_CHECK("1.000e-03", rc);
dv = 1E-3;
TEST_PRF(&rc, "%g", dv);
PRF_CHECK("0.001", rc);
dv = 1234567.89;
TEST_PRF(&rc, "%g", dv);
PRF_CHECK("1.23457e+06", rc);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
dv = (double)BIT64(40);
TEST_PRF(&rc, "/%a/%.4a/%.20a/", dv, dv, dv);
PRF_CHECK("/0x1p+40/0x1.0000p+40/"
"0x1.00000000000000000000p+40/", rc);
dv += (double)BIT64(32);
TEST_PRF(&rc, "%a", dv);
PRF_CHECK("0x1.01p+40", rc);
}
dv = INFINITY;
TEST_PRF(&rc, "%f.f %F.F %e.e %E.E %g.g %G.g %a.a %A.A",
dv, dv, dv, dv, dv, dv, dv, dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
PRF_CHECK("inf.f INF.F inf.e INF.E "
"inf.g INF.g inf.a INF.A", rc);
} else {
PRF_CHECK("inf.f INF.F inf.e INF.E "
"inf.g INF.g %a.a %A.A", rc);
}
dv = -INFINITY;
TEST_PRF(&rc, "%f.f %F.F %e.e %E.E %g.g %G.g %a.a %A.A",
dv, dv, dv, dv, dv, dv, dv, dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
PRF_CHECK("-inf.f -INF.F -inf.e -INF.E "
"-inf.g -INF.g -inf.a -INF.A", rc);
} else {
PRF_CHECK("-inf.f -INF.F -inf.e -INF.E "
"-inf.g -INF.g %a.a %A.A", rc);
}
dv = NAN;
TEST_PRF(&rc, "%f.f %F.F %e.e %E.E %g.g %G.g %a.a %A.A",
dv, dv, dv, dv, dv, dv, dv, dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
PRF_CHECK("nan.f NAN.F nan.e NAN.E "
"nan.g NAN.g nan.a NAN.A", rc);
} else {
PRF_CHECK("nan.f NAN.F nan.e NAN.E "
"nan.g NAN.g %a.a %A.A", rc);
}
dv = DBL_MIN;
TEST_PRF(&rc, "%a %e", dv, dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
PRF_CHECK("0x1p-1022 2.225074e-308", rc);
} else {
PRF_CHECK("%a 2.225074e-308", rc);
}
dv /= 4;
TEST_PRF(&rc, "%a %e", dv, dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
PRF_CHECK("0x0.4p-1022 5.562685e-309", rc);
} else {
PRF_CHECK("%a 5.562685e-309", rc);
}
/*
* The following tests are tailored to exercise edge cases in
* lib/os/cbprintf_complete.c:encode_float() and related functions.
*/
dv = 0x1.0p-3;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("0.125", rc);
dv = 0x1.0p-4;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("0.0625", rc);
dv = 0x1.8p-4;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("0.09375", rc);
dv = 0x1.cp-4;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("0.109375", rc);
dv = 0x1.9999999800000p-7;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("0.01249999999708962", rc);
dv = 0x1.9999999ffffffp-8;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("0.006250000005820765", rc);
dv = 0x1.0p+0;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("1", rc);
dv = 0x1.fffffffffffffp-1022;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("4.450147717014402e-308", rc);
dv = 0x1.ffffffffffffep-1022;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("4.450147717014402e-308", rc);
dv = 0x1.ffffffffffffdp-1022;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("4.450147717014401e-308", rc);
dv = 0x1.0000000000001p-1022;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("2.225073858507202e-308", rc);
dv = 0x1p-1022;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("2.225073858507201e-308", rc);
dv = 0x0.fffffffffffffp-1022;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("2.225073858507201e-308", rc);
dv = 0x0.0000000000001p-1022;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("4.940656458412465e-324", rc);
dv = 0x1.1fa182c40c60dp-1019;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("2e-307", rc);
dv = 0x1.fffffffffffffp+1023;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("1.797693134862316e+308", rc);
dv = 0x1.ffffffffffffep+1023;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("1.797693134862316e+308", rc);
dv = 0x1.ffffffffffffdp+1023;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("1.797693134862315e+308", rc);
dv = 0x1.0000000000001p+1023;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("8.988465674311582e+307", rc);
dv = 0x1p+1023;
TEST_PRF(&rc, "%.16g", dv);
PRF_CHECK("8.98846567431158e+307", rc);
}
static void test_fp_length(void)
{
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("skipped test for nano\n");
return;
}
double dv = 1.2345;
int rc;
TEST_PRF(&rc, "/%g/", dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
PRF_CHECK("/1.2345/", rc);
} else {
PRF_CHECK("/%g/", rc);
}
TEST_PRF(&rc, "/%lg/", dv);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
PRF_CHECK("/1.2345/", rc);
} else {
PRF_CHECK("/%lg/", rc);
}
TEST_PRF_LONG_DOUBLE(&rc, "/%Lg/", (long double)dv);
if (ENABLED_USE_LIBC) {
PRF_CHECK("/1.2345/", rc);
} else {
PRF_CHECK("/%Lg/", rc);
}
/* These have to be tested without the format validation
* attribute because they produce diagnostics, but we have
* intended behavior so we have to test them.
*/
reset_out();
rc = rawprf("/%hf/", dv);
zassert_equal(rc, 5, "len %d", rc);
zassert_equal(strncmp("/%hf/", buf, rc), 0, NULL);
}
static void test_fp_flags(void)
{
if (!IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
TC_PRINT("skipping unsupported feature\n");
return;
}
double dv = 1.23;
int rc;
TEST_PRF(&rc, "/%g/% g/%+g/", dv, dv, dv);
PRF_CHECK("/1.23/ 1.23/+1.23/", rc);
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
TEST_PRF(&rc, "/%a/%.1a/%.2a/", dv, dv, dv);
PRF_CHECK("/0x1.3ae147ae147aep+0/"
"0x1.4p+0/0x1.3bp+0/", rc);
}
dv = -dv;
TEST_PRF(&rc, "/%g/% g/%+g/", dv, dv, dv);
PRF_CHECK("/-1.23/-1.23/-1.23/", rc);
dv = 23;
TEST_PRF(&rc, "/%g/%#g/%.0f/%#.0f/", dv, dv, dv, dv);
PRF_CHECK("/23/23.0000/23/23./", rc);
rc = prf(NULL, "% .380f", 0x1p-400);
zassert_equal(rc, 383, NULL);
zassert_equal(strncmp(buf, " 0.000", 6), 0, NULL);
zassert_equal(strncmp(&buf[119], "00003872", 8), 0, NULL);
}
static void test_star_width(void)
{
int rc;
TEST_PRF(&rc, "/%3c/%-3c/", 'a', 'a');
PRF_CHECK("/ a/a /", rc);
TEST_PRF(&rc, "/%*c/%*c/", 3, 'a', -3, 'a');
PRF_CHECK("/ a/a /", rc);
}
static void test_star_precision(void)
{
int rc;
TEST_PRF(&rc, "/%.*x/%10.*x/",
5, 0x12, 5, 0x12);
PRF_CHECK("/00012/ 00012/", rc);
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("short test for nano\n");
return;
}
if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
double dv = 1.2345678;
TEST_PRF(&rc, "/%.3g/%.5g/%.8g/%g/",
dv, dv, dv, dv);
PRF_CHECK("/1.23/1.2346/1.2345678/1.23457/", rc);
TEST_PRF(&rc, "/%.*g/%.*g/%.*g/%.*g/",
3, dv,
5, dv,
8, dv,
-3, dv);
PRF_CHECK("/1.23/1.2346/1.2345678/1.23457/", rc);
}
}
static void test_n(void)
{
if (!IS_ENABLED(CONFIG_CBPRINTF_N_SPECIFIER)) {
TC_PRINT("skipping unsupported feature\n");
return;
}
if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
TC_PRINT("skipped test for nano\n");
return;
}
char l_hh = 0;
short l_h = 0;
int l = 0;
long l_l = 0;
long long l_ll = 0;
intmax_t l_j = 0;
size_t l_z = 0;
ptrdiff_t l_t = 0;
int rc;
rc = prf(NULL, "12345%n", &l);
zassert_equal(l, rc, "%d != %d", l, rc);
zassert_equal(rc, 5, NULL);
rc = prf(NULL, "12345%hn", &l_h);
zassert_equal(l_h, rc, NULL);
rc = prf(NULL, "12345%hhn", &l_hh);
zassert_equal(l_hh, rc, NULL);
rc = prf(NULL, "12345%ln", &l_l);
zassert_equal(l_l, rc, NULL);
rc = prf(NULL, "12345%lln", &l_ll);
zassert_equal(l_ll, rc, NULL);
rc = prf(NULL, "12345%jn", &l_j);
zassert_equal(l_j, rc, NULL);
rc = prf(NULL, "12345%zn", &l_z);
zassert_equal(l_z, rc, NULL);
rc = prf(NULL, "12345%tn", &l_t);
zassert_equal(l_t, rc, NULL);
}
#define EXPECTED_1ARG(_t) (IS_ENABLED(CONFIG_CBPRINTF_NANO) \
? 1U : (sizeof(_t) / sizeof(int)))
static void test_p(void)
{
if (ENABLED_USE_LIBC) {
TC_PRINT("skipping on libc\n");
return;
}
uintptr_t uip = 0xcafe21;
void *ptr = (void *)uip;
int rc;
TEST_PRF(&rc, "%p", ptr);
PRF_CHECK("0xcafe21", rc);
TEST_PRF(&rc, "%p", NULL);
PRF_CHECK("(nil)", rc);
reset_out();
rc = rawprf("/%12p/", ptr);
zassert_equal(rc, 14, NULL);
zassert_equal(strncmp("/ 0xcafe21/", buf, rc), 0, NULL);
reset_out();
rc = rawprf("/%12p/", NULL);
zassert_equal(rc, 14, NULL);
zassert_equal(strncmp("/ (nil)/", buf, rc), 0, NULL);
reset_out();
rc = rawprf("/%-12p/", ptr);
zassert_equal(rc, 14, NULL);
zassert_equal(strncmp("/0xcafe21 /", buf, rc), 0, NULL);
reset_out();
rc = rawprf("/%-12p/", NULL);
zassert_equal(rc, 14, NULL);
zassert_equal(strncmp("/(nil) /", buf, rc), 0, NULL);
reset_out();
rc = rawprf("/%.8p/", ptr);
zassert_equal(rc, 12, NULL);
zassert_equal(strncmp("/0x00cafe21/", buf, rc), 0, NULL);
}
static int out_counter(int c,
void *ctx)
{
size_t *count = ctx;
++*count;
return c;
}
static int out_e42(int c,
void *ctx)
{
return -42;
}
static void test_libc_substs(void)
{
if (!IS_ENABLED(CONFIG_CBPRINTF_LIBC_SUBSTS)) {
TC_PRINT("not enabled\n");
return;
}
char lbuf[8];
char full_flag = 0xbf;
size_t count = 0;
size_t const len = sizeof(lbuf) - 1U;
int rc;
lbuf[len] = full_flag;
rc = snprintfcb(lbuf, len, "%06d", 1);
zassert_equal(rc, 6, NULL);
zassert_equal(strncmp("000001", lbuf, rc), 0, NULL);
zassert_equal(lbuf[7], full_flag, NULL);
rc = snprintfcb(lbuf, len, "%07d", 1);
zassert_equal(rc, 7, NULL);
zassert_equal(strncmp("000000", lbuf, rc), 0, NULL);
zassert_equal(lbuf[7], full_flag, NULL);
rc = snprintfcb(lbuf, len, "%020d", 1);
zassert_equal(rc, 20, "rc %d", rc);
zassert_equal(lbuf[7], full_flag, NULL);
zassert_equal(strncmp("000000", lbuf, rc), 0, NULL);
rc = cbprintf(out_counter, &count, "%020d", 1);
zassert_equal(rc, 20, "rc %d", rc);
zassert_equal(count, 20, NULL);
if (!IS_ENABLED(CONFIG_CBPRINTF_NANO)) {
rc = cbprintf(out_e42, NULL, "%020d", 1);
zassert_equal(rc, -42, "rc %d", rc);
}
}
static void test_cbprintf_package(void)
{
if (!ENABLED_USE_PACKAGED) {
TC_PRINT("disabled\n");
return;
}
int rc;
char fmt[] = "/%i/"; /* not const */
/* Verify we can calculate length without storing */
rc = cbprintf_package(NULL, PKG_ALIGN_OFFSET, PACKAGE_FLAGS, fmt, 3);
zassert_true(rc > sizeof(int), NULL);
/* Capture the base package information for future tests. */
size_t len = rc;
/* Create a buffer aligned to max argument. */
uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) buf[len + PKG_ALIGN_OFFSET];
/* Verify we get same length when storing. Pass buffer which may be
* unaligned. Same alignment offset was used for space calculation.
*/
rc = cbprintf_package(&buf[PKG_ALIGN_OFFSET], len, PACKAGE_FLAGS, fmt, 3);
zassert_equal(rc, len, NULL);
/* Verify we get an error if can't store */
len -= 1;
rc = cbprintf_package(&buf[PKG_ALIGN_OFFSET], len, PACKAGE_FLAGS, fmt, 3);
zassert_equal(rc, -ENOSPC, NULL);
}
/* Test using @ref CBPRINTF_PACKAGE_ADD_STRING_IDXS flag.
* Note that only static packaging is tested here because ro string detection
* does not work on host testing.
*/
static void test_cbprintf_package_rw_string_indexes(void)
{
if (!ENABLED_USE_PACKAGED) {
TC_PRINT("disabled\n");
return;
}
if (!Z_C_GENERIC) {
/* runtime packaging will not detect ro strings. */
return;
}
int len0, len1;
static const char *test_str = "test %d %s";
static const char *test_str1 = "lorem ipsum";
uint8_t str_idx;
char *addr;
CBPRINTF_STATIC_PACKAGE(NULL, 0, len0, 0, CBPRINTF_PACKAGE_CONST_CHAR_RO,
test_str, 100, test_str1);
CBPRINTF_STATIC_PACKAGE(NULL, 0, len1, 0,
CBPRINTF_PACKAGE_ADD_STRING_IDXS,
test_str, 100, test_str1);
/* package with string indexes will contain two more bytes holding indexes
* of string parameter locations.
*/
zassert_equal(len0 + 2, len1, NULL);
uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package0[len0];
uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package1[len1];
CBPRINTF_STATIC_PACKAGE(package0, sizeof(package0), len0, 0,
CBPRINTF_PACKAGE_CONST_CHAR_RO,
test_str, 100, test_str1);
CBPRINTF_STATIC_PACKAGE(package1, sizeof(package1), len1, 0,
CBPRINTF_PACKAGE_ADD_STRING_IDXS,
test_str, 100, test_str1);
union cbprintf_package_hdr *desc0 = (union cbprintf_package_hdr *)package0;
union cbprintf_package_hdr *desc1 = (union cbprintf_package_hdr *)package1;
/* Compare descriptor content. Second package has one ro string index. */
zassert_equal(desc0->desc.ro_str_cnt, 0, NULL);
zassert_equal(desc1->desc.ro_str_cnt, 2, NULL);
zassert_equal(len0 + 2, len1, NULL);
int *p = (int *)package1;
str_idx = package1[len0];
addr = *(char **)&p[str_idx];
zassert_equal(addr, test_str, NULL);
str_idx = package1[len0 + 1];
addr = *(char **)&p[str_idx];
zassert_equal(addr, test_str1, NULL);
}
static int fsc_package_cb(int c, void *ctx)
{
char **p = ctx;
(*p)[0] = c;
*p = *p + 1;
return c;
}
/* Test for validating conversion to fully self-contained package. */
static void test_cbprintf_fsc_package(void)
{
if (!ENABLED_USE_PACKAGED) {
TC_PRINT("disabled\n");
return;
}
if (!Z_C_GENERIC) {
/* runtime packaging will not detect ro strings. */
return;
}
char test_str[] = "test %d %s";
const char *test_str1 = "lorem ipsum";
char exp_str0[256];
char exp_str1[256];
char out_str[256];
char *pout;
int len;
int fsc_len;
int err;
snprintf(exp_str0, sizeof(exp_str0), test_str, 100, test_str1);
CBPRINTF_STATIC_PACKAGE(NULL, 0, len, 0,
CBPRINTF_PACKAGE_ADD_STRING_IDXS,
test_str, 100, test_str1);
zassert_true(len > 0, NULL);
uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) package[len];
CBPRINTF_STATIC_PACKAGE(package, sizeof(package), len, 0,
CBPRINTF_PACKAGE_ADD_STRING_IDXS,
test_str, 100, test_str1);
/* Get length of fsc package. */
fsc_len = cbprintf_fsc_package(package, len, NULL, 0);
int exp_len = len + (int)strlen(test_str) + 1 + (int)strlen(test_str1) + 1;
zassert_equal(exp_len, fsc_len, NULL);
uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) fsc_package[fsc_len];
err = cbprintf_fsc_package(package, len, fsc_package, fsc_len - 1);
zassert_equal(err, -ENOSPC, NULL);
err = cbprintf_fsc_package(package, len, fsc_package, fsc_len);
zassert_equal(err, fsc_len, NULL);
/* Now overwrite a char in original string, confirm that fsc package
* contains string without that change because ro string is copied into
* the package.
*/
test_str[0] = 'w';
snprintf(exp_str1, sizeof(exp_str1), test_str, 100, test_str1);
pout = out_str;
cbpprintf(fsc_package_cb, &pout, package);
*pout = '\0';
zassert_equal(strcmp(out_str, exp_str1), 0, NULL);
zassert_true(strcmp(exp_str0, exp_str1) != 0, NULL);
/* FSC package contains original content. */
pout = out_str;
cbpprintf(fsc_package_cb, &pout, fsc_package);
*pout = '\0';
zassert_equal(strcmp(out_str, exp_str0), 0, NULL);
}
static void test_cbpprintf(void)
{
if (!ENABLED_USE_PACKAGED) {
TC_PRINT("disabled\n");
return;
}
int rc;
/* This only checks error conditions. Formatting is checked
* by diverting prf() and related helpers to use the packaged
* version.
*/
reset_out();
rc = cbpprintf(out, &outbuf, NULL);
zassert_equal(rc, -EINVAL, NULL);
}
static void test_nop(void)
{
}
/*test case main entry*/
void test_main(void)
{
if (sizeof(int) == 4) {
pfx_str += 8U;
sfx_str += 8U;
}
TC_PRINT("Opts: " COND_CODE_1(M64_MODE, ("m64"), ("m32")) "\n");
if (ENABLED_USE_LIBC) {
TC_PRINT(" LIBC");
}
if (IS_ENABLED(CONFIG_CBPRINTF_COMPLETE)) {
TC_PRINT(" COMPLETE");
} else {
TC_PRINT(" NANO\n");
}
if (ENABLED_USE_PACKAGED) {
TC_PRINT(" PACKAGED %s C11 _Generic\n",
Z_C_GENERIC ? "with" : "without");
} else {
TC_PRINT(" VA_LIST\n");
}
if (IS_ENABLED(CONFIG_CBPRINTF_FULL_INTEGRAL)) {
TC_PRINT(" FULL_INTEGRAL\n");
} else {
TC_PRINT(" REDUCED_INTEGRAL\n");
}
if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) {
TC_PRINT(" FP_SUPPORT\n");
}
if (IS_ENABLED(CONFIG_CBPRINTF_FP_A_SUPPORT)) {
TC_PRINT(" FP_A_SUPPORT\n");
}
if (IS_ENABLED(CONFIG_CBPRINTF_N_SPECIFIER)) {
TC_PRINT(" FP_N_SPECIFIER\n");
}
if (IS_ENABLED(CONFIG_CBPRINTF_LIBC_SUBSTS)) {
TC_PRINT(" LIBC_SUBSTS\n");
}
printf("sizeof: int=%zu long=%zu ptr=%zu long long=%zu double=%zu long double=%zu\n",
sizeof(int), sizeof(long), sizeof(void *), sizeof(long long),
sizeof(double), sizeof(long double));
printf("alignof: int=%zu long=%zu ptr=%zu long long=%zu double=%zu long double=%zu\n",
__alignof__(int), __alignof__(long), __alignof__(void *),
__alignof__(long long), __alignof__(double), __alignof__(long double));
#ifdef CONFIG_CBPRINTF_COMPLETE
printf("sizeof(conversion) = %zu\n", sizeof(struct conversion));
#endif
#ifdef USE_PACKAGED
printf("package alignment offset = %zu\n", PKG_ALIGN_OFFSET);
#endif
ztest_test_suite(test_prf,
ztest_unit_test(test_pct),
ztest_unit_test(test_v_c),
ztest_unit_test(test_c),
ztest_unit_test(test_s),
ztest_unit_test(test_d_length),
ztest_unit_test(test_d_flags),
ztest_unit_test(test_x_length),
ztest_unit_test(test_x_flags),
ztest_unit_test(test_o),
ztest_unit_test(test_fp_value),
ztest_unit_test(test_fp_length),
ztest_unit_test(test_fp_flags),
ztest_unit_test(test_star_width),
ztest_unit_test(test_star_precision),
ztest_unit_test(test_n),
ztest_unit_test(test_p),
ztest_unit_test(test_libc_substs),
ztest_unit_test(test_cbprintf_package),
ztest_unit_test(test_cbpprintf),
ztest_unit_test(test_cbprintf_package_rw_string_indexes),
ztest_unit_test(test_cbprintf_fsc_package),
ztest_unit_test(test_nop)
);
ztest_run_test_suite(test_prf);
}