testing/libc/arch_libc: Extend coverage to all string/memory functions - #3712
Open
xiaoxiang781216 wants to merge 4 commits into
Open
testing/libc/arch_libc: Extend coverage to all string/memory functions#3712xiaoxiang781216 wants to merge 4 commits into
xiaoxiang781216 wants to merge 4 commits into
Conversation
The arch_libc test only covered strcpy, so the architecture optimized implementations of the remaining string and memory routines were never exercised by the test suite. Extend the test to also cover memcpy, memmove, memset, memcmp, memchr, strlen, strcmp, strchr, strncmp, strnlen, strncpy, stpcpy, strcat and strrchr: * Every function gets a correctness test that sweeps the buffer alignment and the transfer size and compares the result against the expected value. * Every function gets a speed test that reports the average cycle count measured with perf_gettime(). * Every individual test is selected by its own CONFIG_TESTING_ARCH_LIBC_<FUNC> option (default y), so a target can drop the ones it does not need. Impact: test only. Nothing is built unless CONFIG_TESTING_ARCH_LIBC (default n) is selected, so no existing board configuration changes. Testing: built and ran sim:nsh on Linux x86_64 (Ubuntu 24.04, gcc 13.3.0) with CONFIG_TESTING_ARCH_LIBC=y. All 15 enabled functions report PASSED and "arch_libc_test Passed". Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Add test_strchrnul() and speed_strchrnul(), selected by the new
CONFIG_TESTING_ARCH_LIBC_STRCHRNUL option, covering the hit, miss and
NUL cases.
Sweep alignment 0..7 and the boundary sizes {0, 1, 7, 8, 9, 15, 16, 17,
31, 32, 33, 63, 64, 65, 127, 128, 129, 255, 256, 257} in the scan
function tests (memcmp, memchr, strlen, strcmp, strchr, strncmp,
strnlen, strrchr) and in memmove. Those sizes sit on the 8 and 16 byte
chunk edges and on the sub-word tails, so vectorized (NEON/MVE) and
word-at-a-time implementations are stressed exactly at their alignment
and size boundaries instead of only at "nice" lengths. memmove is
additionally exercised across four overlap layouts: forward, backward,
contained and adjacent.
Impact: test only, selected by CONFIG_TESTING_ARCH_LIBC (default n).
Testing: built and ran qemu-armv7a:nsh (Cortex-A7, generic C
implementation) and sim:nsh on Linux x86_64 (Ubuntu 24.04, gcc 13.3.0)
with CONFIG_TESTING_ARCH_LIBC=y. All 16 enabled functions report
PASSED and "arch_libc_test Passed". These tests pass against the
generic C routines, which establishes the correctness baseline before
architecture optimized assembly is introduced.
Signed-off-by: anjiahao <anjiahao@xiaomi.com>
The adjacent overlap case in test_memmove() placed the source at a fixed g_buf1 + align + 64 and the destination one size further, so the destination tail reached align + 64 + 2 * size. g_buf1 is only TEST_BUF_SIZE + MAX_ALIGN (528) bytes, so the larger swept sizes ran off the end: align=0 with size=255 writes up to offset 573, that is 46 bytes past the object. AddressSanitizer aborted arch_libctest with a global-buffer-overflow. Start the adjacent layout at g_buf1 + align instead. The tail then reaches align + 2 * size, which is at most 7 + 2 * 257 = 521 and stays inside g_buf1 for every alignment and boundary size that is swept, while still keeping source and destination exactly adjacent. Impact: test only, selected by CONFIG_TESTING_ARCH_LIBC (default n). Testing: built and ran sim:nsh on Linux x86_64 (Ubuntu 24.04, gcc 13.3.0) with CONFIG_TESTING_ARCH_LIBC=y. memmove reports PASSED with no sanitizer report, and "arch_libc_test Passed". Assisted-by: Claude:claude-opus-5 Signed-off-by: dengwenqi <dengwenqi@xiaomi.com>
test_strcpy(), test_strncpy() and test_stpcpy() applied the same offset to the source and to the destination, so both pointers always shared the same word congruence. Architecture optimized copy routines take a different code path when the two offsets differ: a byte prologue to align the destination, then either a byte fallback or a shift-merge loop that recombines two source words per store. None of that was reached by the test. Vary the source and destination offsets independently over 0..7 in those three tests, so both the equal congruence (aligned word copy) and the unequal congruence (shift-merge) paths are covered, and report both offsets on failure so a regression points at the offending combination. Also drop the ARCH_TOOLCHAIN_GNU dependency from TESTING_ARCH_LIBC. The test only uses standard C string functions and perf_gettime(), with no GNU specific construct, so it builds with non GNU toolchains such as TASKING as well. Impact: test only, selected by CONFIG_TESTING_ARCH_LIBC (default n). Dropping the ARCH_TOOLCHAIN_GNU dependency only widens the set of toolchains that may select the test, no existing configuration changes. Testing: built and ran sim:nsh on Linux x86_64 (Ubuntu 24.04, gcc 13.3.0) with CONFIG_TESTING_ARCH_LIBC=y. strcpy, strncpy and stpcpy report PASSED for all 64 offset combinations, and "arch_libc_test Passed". Assisted-by: Claude:claude-opus-5 Signed-off-by: zhangyuan29 <zhangyuan29@xiaomi.com>
5 tasks
cederom
approved these changes
Aug 9, 2026
cederom
left a comment
Contributor
There was a problem hiding this comment.
Thank you @xiaoxiang781216 :-)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
apps/testing/libc/arch_libconly exercisedstrcpy(), so the architectureoptimized implementations of every other string and memory routine were never
covered by the test suite. This series turns it into a full correctness and
speed harness for the whole string/memory family, which is the prerequisite for
landing architecture optimized assembly with confidence.
Four commits:
Add tests for all string/memory functions.Adds a correctness test (sweeping buffer alignment and transfer size) and a
speed test (average cycles via
perf_gettime()) formemcpy,memmove,memset,memcmp,memchr,strlen,strcmp,strchr,strncmp,strnlen,strncpy,stpcpy,strcatandstrrchr. Each test isselected by its own
CONFIG_TESTING_ARCH_LIBC_<FUNC>option (default y) soa target can drop the ones it does not need.
Add strchrnul test and sweep size boundaries.Adds
strchrnulcoverage, and sweeps alignment 0..7 together with theboundary sizes {0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128,
129, 255, 256, 257} in the scan function tests and in
memmove. Thosesizes sit on the 8/16-byte chunk edges and on the sub-word tails, so
vectorized (NEON/MVE) and word-at-a-time implementations are stressed
exactly at their alignment and size boundaries.
memmoveis additionallyexercised across four overlap layouts: forward, backward, contained and
adjacent.
Fix out-of-bounds write in memmove test.The adjacent overlap layout introduced by (2) started at a fixed
g_buf1 + align + 64, so the destination tail ran pastg_buf1for thelargest swept sizes (AddressSanitizer reported a global-buffer-overflow).
Start the layout at
g_buf1 + aligninstead.Cover unaligned src/dst copy paths.strcpy/strncpy/stpcpyapplied the same offset to source anddestination, so the two pointers always shared the same word congruence and
the byte prologue plus shift-merge path of optimized copy routines was never
reached. Vary both offsets independently over 0..7. Also drops the
ARCH_TOOLCHAIN_GNUdependency fromTESTING_ARCH_LIBC: the test only usesstandard C string functions and
perf_gettime(), with no GNU specificconstruct, so it builds with non-GNU toolchains such as TASKING as well.
Commit 3 is a fix for commit 2 rather than a squash because the two commits
have different authors; each commit still builds and runs standalone
(see Testing).
Impact
CONFIG_TESTING_ARCH_LIBC(default n) is selected, so no existing board configuration or defconfig
changes, and no size impact on any shipped build.
TESTING_ARCH_LIBC_{MEMCHR,MEMCMP,MEMCPY,MEMMOVE,MEMSET, STRCHR,STRCMP,STRCPY,STRLEN,STRNCMP,STRNLEN,STRNCPY,STPCPY,STRCAT,STRRCHR, STRCHRNUL}, all default y insideTESTING_ARCH_LIBC.ARCH_TOOLCHAIN_GNUdependency only widens the set oftoolchains that may select the test; no existing configuration changes
behaviour.
Testing
Host: Ubuntu 24.04 x86_64, gcc 13.3.0
Target:
sim:nshwithCONFIG_TESTING_ARCH_LIBC=y(all 16 function optionsenabled) and
CONFIG_TESTING_ARCH_LIBC_VERBOSE=yEvery commit of the series was built and run standalone; no build warnings, and
all enabled functions report
PASSED:Add tests for all string/memory functions.arch_libc_test PassedAdd strchrnul test and sweep size boundaries.arch_libc_test PassedFix out-of-bounds write in memmove test.arch_libc_test PassedCover unaligned src/dst copy paths.arch_libc_test PassedA build with only
CONFIG_TESTING_ARCH_LIBC_STRCPY=y(every other functiontest disabled) was also checked to make sure the reduced configurations stay
warning free.
Before (
apache/master, onlystrcpyis covered):After (this series):
tools/checkpatch.sh -c -u -m -g apache/master..HEADreportsAll checks pass.for the series.