Skip to content

testing/libc/printftest: Follow the printf options. - #3994

Draft
casaroli wants to merge 4 commits into
apache:masterfrom
casaroli:pt-output
Draft

casaroli wants to merge 4 commits into
apache:masterfrom
casaroli:pt-output

Conversation

@casaroli

@casaroli casaroli commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

depends-on: apache/nuttx/pull/21595

Part of apache/nuttx#21467.

Summary

Tests of printf() for the merged apache/nuttx#21505 and apache/nuttx#21507, and for apache/nuttx#21595. Four commits:

  1. printftest follows the printf options. It expected the output of the Default profile, so it failed with the other profiles of libc and when one printf option was turned off. Each case now follows LIBC_FLOATINGPOINT, LIBC_NUMBERED_ARGS, LIBC_PRINTF_ALT_FORM, LIBC_PRINTF_INT_PRECISION, LIBC_PRINTF_OCTAL (%o prints "?"), LIBC_PRINTF_LEFT_JUSTIFY (the - flag pads on the left), LIBC_PRINTF_HEXFLOAT, LIBC_PRINTF_C23 and LIBC_PRINTF_PERCENT_N. LIBC_PRINTF_SHORT and LIBC_PRINTF_LONG_LONG change no case: %hhn and %lln store at their size with both settings. New cases: the sign of -0.0, %a and %A, %b and %B, and the wN length. A precision of INT_MIN from * is no precision, so %.*d|%.*s| expects 1|ab| in all profiles.
  2. printftest: cases for %#g, which keeps the trailing zeros (%#g of 1.0 is 1.00000, %#.0g of 1.0 is 1.), and for a negative precision from *, which is no precision (%.*s with -2 prints the whole string, %0*.*d keeps the 0 flag).
  3. A new program, printfengine, checks the digits of %e, %f and %g: ties of values that are exact in binary, %.0f rounds, the form of %g, the sign, infinity and NaN, the limits of binary64 and 17 correct digits. With LIBC_PRINTF_EXACT it checks all digits of a double, and with LIBC_PRINTF_EXACT_LDOUBLE the range and the digits of a long double. It follows printftest: the same layout, and Make and CMake files.
  4. printftest: %n prints nothing also when LIBC_PRINTF_PERCENT_N is off (libs/libc/stream: Print nothing for %n when LIBC_PRINTF_PERCENT_N is off. nuttx#21595), where it printed ? before. The test expects the same text with the option on or off, and checks the store only when the option is on. New case: snprintf(NULL, 0, "ab%n|%s", &n, "str") returns 6.

Impact

testing/libc/printftest/printftest_main.c, and the new program in testing/libc/printfengine with the option CONFIG_TESTING_PRINTFENGINE, off by default. It depends on LIBC_FLOATINGPOINT. No change to any other code.

Commit 4 needs apache/nuttx#21595: on master printftest fails at %n with LIBC_PRINTF_PERCENT_N off. So this PR must merge after it.

Testing

qemu-armv8a under QEMU with HVF, nuttx apache/nuttx#21595 (9ae1b2e6d85, on master d1191e0ad01), printftest, printfengine, then ostest; each run passes and ostest exits with status 0:

build printf settings
qemu-armv8a:knsh (kernel) Default
qemu-armv8a:knsh Full
qemu-armv8a:knsh Minimal
qemu-armv8a:knsh Default, LIBC_PRINTF_OCTAL=n, LIBC_PRINTF_LEFT_JUSTIFY=n
qemu-armv8a:knsh Full, LIBC_PRINTF_PERCENT_N=y
qemu-armv8a:knsh Minimal, LIBC_PRINTF_PERCENT_N=y, LIBC_PRINTF_OCTAL=n, LIBC_PRINTF_LEFT_JUSTIFY=n
qemu-armv8a:nsh (flat) Default
qemu-armv8a:nsh Full, LIBC_PRINTF_PERCENT_N=y

printfengine needs floating point, so it does not run with Minimal.

On nuttx master d1191e0ad01 (qemu-armv8a:knsh, Default) printftest fails at commit 4, as it must: "ab%n|%s" returned 7: "ab?|str", expected "ab|str". printfengine passes there. With LIBC_PRINTF_PERCENT_N=y both pass on master.

Builds with -Werror and both programs on: qemu-armv8a:nsh and rv-virt:nsh64, each with Default and with Full and LIBC_PRINTF_PERCENT_N=y.

tools/checkpatch.sh -c -u -m -g passes.

Not run: a CMake build, a protected build, hardware.

xiaoxiang781216
xiaoxiang781216 previously approved these changes Nov 9, 2026
The test expects the output of the Default profile.  Make each case follow
the options of printf(), so that it also passes with the Minimal and Full
profiles of libc, and with each option turned on or off on its own.
LIBC_PRINTF_SHORT and LIBC_PRINTF_LONG_LONG change no case: %hhn and %lln
store at their size with both settings.

Add cases for -0.0, %a and %A, %b and %B, and the wN length.

Part of apache/nuttx#21467

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
printf() now keeps the trailing zeros of %#g, and it takes a negative
precision from * as no precision, as C says.  Add cases for both.

Part of apache/nuttx#21467

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Add the program printfengine.  It checks the digits of %e, %f and %g: ties of
values that are exact in binary, %.0f rounds, the form of %g, the sign,
infinity, NaN, the limits of binary64 and 17 correct digits.

With LIBC_PRINTF_EXACT it also checks all digits of a double, and with
LIBC_PRINTF_EXACT_LDOUBLE the range and the digits of a long double.

Each format goes through a function with no format attribute.  An error prints
the format and stops with an assertion.

Part of apache/nuttx#21467

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
printf() now prints nothing for %n also when LIBC_PRINTF_PERCENT_N is off,
where it printed "?" before.  The test expects the same text with the
option on or off, and checks the store only when the option is on.

Add a check that snprintf(NULL, 0, ...) returns the length without the %n.

Part of apache/nuttx#21467

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants