Changeset View
Standalone View
lib/libc/tests/string/strrchr_test.c
- This file was added.
| /*- | |||||
| * SPDX-License-Identifier: BSD-2-Clause | |||||
| * | |||||
| * Copyright (c) 2023, 2026 Robert Clausecker <fuz@FreeBSD.org> | |||||
| */ | |||||
| #include <sys/cdefs.h> | |||||
| #include <dlfcn.h> | |||||
| #include <limits.h> | |||||
| #include <stdio.h> | |||||
| #include <string.h> | |||||
| #include <atf-c.h> | |||||
| static char *(*strrchr_fn)(const char *, int); | |||||
| ATF_TC_WITHOUT_HEAD(nul); | |||||
| ATF_TC_BODY(nul, tc) | |||||
| { | |||||
| size_t i, j, k; | |||||
| char buf[1+15+64]; /* offset [0+15] + 64 buffer bytes + sentinels */ | |||||
| buf[0] = '\0'; | |||||
| memset(buf + 1, '-', sizeof(buf) - 1); | |||||
| for (i = 0; i < 16; i++) | |||||
| for (j = 0; j < 64; j++) | |||||
ngie: Could these please be made into constants? | |||||
fuzAuthorUnsubmitted Done Inline ActionsI'm not sure if this would be helpful here. These numbers correspond to the possible choices in the SSE implementation, which processes 16 bytes per vector (thus 16 possibly misalignments) and 32 bytes per iteration (thus 64 bytes total length to complete the main loop at least once). If I change the code such that these values change, I plan to bump the unit test to cover the extended range. The same applies to the other cases and in fact pretty much all the string unit tests I have written so far. I can add some arbitrary symbolic names for these numbers, but I don't see how that improves things, it just adds more clutter. If you insist, I can try and do some systematic refactoring to add symbolic constants at a later point, but it makes the unit tests less useful as a development tool for me, as it becomes harder to modify the numbers when the code changes. My main priority is to get the fix for 293915 in right now. fuz: I'm not sure if this would be helpful here. These numbers correspond to the possible choices… | |||||
| for (k = j; k < 64; k++) { | |||||
Not Done Inline Actionsnit: I would specify alignas(16) for better repeatability. I'm not 100% convinced it won't fail on i = 4 for one version of the compiler, but 8 for another, if the stack layout is changed strajabot: nit: I would specify `alignas(16) ` for better repeatability. I'm not 100% convinced it won't… | |||||
Done Inline Actions
Indeed, but it'll cycle through all alignments anyway and the specific iteration it fails on doesn't really matter. fuz: > nit: I would specify `alignas(16) ` for better repeatability. I'm not 100% convinced it won't… | |||||
| buf[i + j + 1] = '\0'; | |||||
| buf[i + k + 1] = '\0'; | |||||
| ATF_CHECK_EQ(strrchr_fn(buf + i + 1, '\0'), buf + i + j + 1); | |||||
| buf[i + j + 1] = '-'; | |||||
| buf[i + k + 1] = '-'; | |||||
| } | |||||
| } | |||||
| ATF_TC_WITHOUT_HEAD(not_found); | |||||
| ATF_TC_BODY(not_found, tc) | |||||
| { | |||||
| size_t i, j; | |||||
| char buf[1+15+64+2]; /* offset [0..15] + 64 buffer bytes + sentinels */ | |||||
| buf[0] = 'X'; | |||||
| memset(buf + 1, '-', sizeof(buf) - 1); | |||||
| for (i = 0; i < 16; i++) | |||||
| for (j = 0; j < 64; j++) { | |||||
ngieUnsubmitted Not Done Inline ActionsCould these please be made into constants? ngie: Could these please be made into constants? | |||||
| buf[i + j + 1] = '\0'; | |||||
| buf[i + j + 2] = 'X'; | |||||
| ATF_CHECK_EQ(strrchr_fn(buf + i + 1, 'X'), NULL); | |||||
| buf[i + j + 1] = '-'; | |||||
| buf[i + j + 2] = '-'; | |||||
| } | |||||
| } | |||||
| static void | |||||
| do_found_test(char buf[], size_t first, size_t second) | |||||
| { | |||||
| /* invariant: first <= second */ | |||||
| buf[first] = 'X'; | |||||
| buf[second] = 'X'; | |||||
| ATF_CHECK_EQ(strrchr_fn(buf, 'X'), buf + second); | |||||
| buf[first] = '-'; | |||||
| buf[second] = '-'; | |||||
| } | |||||
| ATF_TC_WITHOUT_HEAD(found); | |||||
| ATF_TC_BODY(found, tc) | |||||
| { | |||||
| size_t i, j, k, l; | |||||
| char buf[1+15+64+2]; | |||||
| buf[0] = 'X'; | |||||
| memset(buf + 1, '-', sizeof(buf) - 1); | |||||
ngieUnsubmitted Not Done Inline ActionsAlso, why X/-? ngie: Also, why X/-? | |||||
fuzAuthorUnsubmitted Done Inline ActionsThe choice is arbitrary. X is the character we are looking for, - is some other character. They were chosen to be easy to distinguish visually when inspecting a test suite failure in the debugger. Unit test values goes through all possible characters to try to catch arithmetic errors in the scalar kernel (cf. 3d8ef25). fuz: The choice is arbitrary. `X` is the character we are looking for, `-` is some other character. | |||||
| for (i = 0; i < 16; i++) | |||||
| for (j = 0; j < 64; j++) | |||||
ngieUnsubmitted Not Done Inline ActionsCould these please be made into constants? ngie: Could these please be made into constants? | |||||
| for (k = 0; k < j; k++) | |||||
| for (l = 0; l <= k; l++) { | |||||
| buf[i + j + 1] = '\0'; | |||||
| buf[i + j + 2] = 'X'; | |||||
| do_found_test(buf + i + 1, l, k); | |||||
| buf[i + j + 1] = '-'; | |||||
| buf[i + j + 2] = '-'; | |||||
| } | |||||
| } | |||||
| /* check that the right character is found */ | |||||
| static void | |||||
| do_values_test(char buf[], size_t len, size_t i, int c) | |||||
| { | |||||
| /* sentinels */ | |||||
| buf[-1] = c; | |||||
| buf[len] = '\0'; | |||||
| buf[len + 1] = 'c'; | |||||
| memset(buf, c == 255 ? c - 1 : c + 1, len); | |||||
| if (i < len) { | |||||
| buf[i] = c; | |||||
| ATF_CHECK_EQ(strrchr_fn(buf, c), buf + i); | |||||
| } else | |||||
| ATF_CHECK_EQ(strrchr_fn(buf, c), c == 0 ? buf + len : NULL); | |||||
| } | |||||
| ATF_TC_WITHOUT_HEAD(values); | |||||
| ATF_TC_BODY(values, tc) | |||||
| { | |||||
| size_t i, j, k; | |||||
| int c; | |||||
| char buf[1+15+64+2]; | |||||
| for (i = 0; i < 16; i++) | |||||
| for (j = 0; j < 64; j++) | |||||
| for (k = 0; k <= j; k++) | |||||
| for (c = 0; c <= UCHAR_MAX; c++) | |||||
| do_values_test(buf + i + 1, j, k, c); | |||||
| } | |||||
| ATF_TP_ADD_TCS(tp) | |||||
| { | |||||
| void *dl_handle; | |||||
| dl_handle = dlopen(NULL, RTLD_LAZY); | |||||
| strrchr_fn = dlsym(dl_handle, "test_strrchr"); | |||||
| if (strrchr_fn == NULL) | |||||
| strrchr_fn = strrchr; | |||||
| ATF_TP_ADD_TC(tp, nul); | |||||
| ATF_TP_ADD_TC(tp, not_found); | |||||
| ATF_TP_ADD_TC(tp, found); | |||||
| ATF_TP_ADD_TC(tp, values); | |||||
| return (atf_no_error()); | |||||
| } | |||||
Could these please be made into constants?