xref: /aosp_15_r20/external/llvm-libc/test/src/string/StrchrTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1*71db0c75SAndroid Build Coastguard Worker //===-- Tests for str{,r}chr and {,r}index functions ------------*- C++ -*-===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker 
9*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h"
10*71db0c75SAndroid Build Coastguard Worker 
11*71db0c75SAndroid Build Coastguard Worker template <auto Func> struct StrchrTest : public LIBC_NAMESPACE::testing::Test {
findsFirstCharacterStrchrTest12*71db0c75SAndroid Build Coastguard Worker   void findsFirstCharacter() {
13*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
14*71db0c75SAndroid Build Coastguard Worker 
15*71db0c75SAndroid Build Coastguard Worker     // Should return original string since 'a' is the first character.
16*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(src, 'a'), "abcde");
17*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
18*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
19*71db0c75SAndroid Build Coastguard Worker   }
20*71db0c75SAndroid Build Coastguard Worker 
findsMiddleCharacterStrchrTest21*71db0c75SAndroid Build Coastguard Worker   void findsMiddleCharacter() {
22*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
23*71db0c75SAndroid Build Coastguard Worker 
24*71db0c75SAndroid Build Coastguard Worker     // Should return characters after (and including) 'c'.
25*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(src, 'c'), "cde");
26*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
27*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
28*71db0c75SAndroid Build Coastguard Worker   }
29*71db0c75SAndroid Build Coastguard Worker 
findsLastCharacterThatIsNotNullTerminatorStrchrTest30*71db0c75SAndroid Build Coastguard Worker   void findsLastCharacterThatIsNotNullTerminator() {
31*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
32*71db0c75SAndroid Build Coastguard Worker 
33*71db0c75SAndroid Build Coastguard Worker     // Should return 'e' and null-terminator.
34*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(src, 'e'), "e");
35*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
36*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
37*71db0c75SAndroid Build Coastguard Worker   }
38*71db0c75SAndroid Build Coastguard Worker 
findsNullTerminatorStrchrTest39*71db0c75SAndroid Build Coastguard Worker   void findsNullTerminator() {
40*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
41*71db0c75SAndroid Build Coastguard Worker 
42*71db0c75SAndroid Build Coastguard Worker     // Should return null terminator.
43*71db0c75SAndroid Build Coastguard Worker     const char *nul_terminator = Func(src, '\0');
44*71db0c75SAndroid Build Coastguard Worker     ASSERT_NE(nul_terminator, nullptr);
45*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(nul_terminator, "");
46*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
47*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
48*71db0c75SAndroid Build Coastguard Worker   }
49*71db0c75SAndroid Build Coastguard Worker 
characterNotWithinStringShouldReturnNullptrStrchrTest50*71db0c75SAndroid Build Coastguard Worker   void characterNotWithinStringShouldReturnNullptr() {
51*71db0c75SAndroid Build Coastguard Worker     // Since 'z' is not within the string, should return nullptr.
52*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("123?", 'z'), nullptr);
53*71db0c75SAndroid Build Coastguard Worker   }
54*71db0c75SAndroid Build Coastguard Worker 
theSourceShouldNotChangeStrchrTest55*71db0c75SAndroid Build Coastguard Worker   void theSourceShouldNotChange() {
56*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
57*71db0c75SAndroid Build Coastguard Worker     // When the character is found, the source string should not change.
58*71db0c75SAndroid Build Coastguard Worker     Func(src, 'd');
59*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
60*71db0c75SAndroid Build Coastguard Worker     // Same case for when the character is not found.
61*71db0c75SAndroid Build Coastguard Worker     Func(src, 'z');
62*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
63*71db0c75SAndroid Build Coastguard Worker     // Same case for when looking for nullptr.
64*71db0c75SAndroid Build Coastguard Worker     Func(src, '\0');
65*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
66*71db0c75SAndroid Build Coastguard Worker   }
67*71db0c75SAndroid Build Coastguard Worker 
shouldFindFirstOfDuplicatesStrchrTest68*71db0c75SAndroid Build Coastguard Worker   void shouldFindFirstOfDuplicates() {
69*71db0c75SAndroid Build Coastguard Worker     // '1' is duplicated in the string, but it should find the first copy.
70*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func("abc1def1ghi", '1'), "1def1ghi");
71*71db0c75SAndroid Build Coastguard Worker 
72*71db0c75SAndroid Build Coastguard Worker     const char *dups = "XXXXX";
73*71db0c75SAndroid Build Coastguard Worker     // Should return original string since 'X' is the first character.
74*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(dups, 'X'), dups);
75*71db0c75SAndroid Build Coastguard Worker   }
76*71db0c75SAndroid Build Coastguard Worker 
emptyStringShouldOnlyMatchNullTerminatorStrchrTest77*71db0c75SAndroid Build Coastguard Worker   void emptyStringShouldOnlyMatchNullTerminator() {
78*71db0c75SAndroid Build Coastguard Worker     // Null terminator should match.
79*71db0c75SAndroid Build Coastguard Worker     const char empty_string[] = "";
80*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(static_cast<const char *>(Func(empty_string, '\0')),
81*71db0c75SAndroid Build Coastguard Worker               empty_string);
82*71db0c75SAndroid Build Coastguard Worker     // All other characters should not match.
83*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("", 'Z'), nullptr);
84*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("", '3'), nullptr);
85*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("", '*'), nullptr);
86*71db0c75SAndroid Build Coastguard Worker   }
87*71db0c75SAndroid Build Coastguard Worker };
88*71db0c75SAndroid Build Coastguard Worker 
89*71db0c75SAndroid Build Coastguard Worker template <auto Func> struct StrrchrTest : public LIBC_NAMESPACE::testing::Test {
findsFirstCharacterStrrchrTest90*71db0c75SAndroid Build Coastguard Worker   void findsFirstCharacter() {
91*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
92*71db0c75SAndroid Build Coastguard Worker 
93*71db0c75SAndroid Build Coastguard Worker     // Should return original string since 'a' is the first character.
94*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(src, 'a'), "abcde");
95*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
96*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
97*71db0c75SAndroid Build Coastguard Worker   }
98*71db0c75SAndroid Build Coastguard Worker 
findsMiddleCharacterStrrchrTest99*71db0c75SAndroid Build Coastguard Worker   void findsMiddleCharacter() {
100*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
101*71db0c75SAndroid Build Coastguard Worker 
102*71db0c75SAndroid Build Coastguard Worker     // Should return characters after (and including) 'c'.
103*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(src, 'c'), "cde");
104*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
105*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
106*71db0c75SAndroid Build Coastguard Worker   }
107*71db0c75SAndroid Build Coastguard Worker 
findsLastCharacterThatIsNotNullTerminatorStrrchrTest108*71db0c75SAndroid Build Coastguard Worker   void findsLastCharacterThatIsNotNullTerminator() {
109*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
110*71db0c75SAndroid Build Coastguard Worker 
111*71db0c75SAndroid Build Coastguard Worker     // Should return 'e' and null-terminator.
112*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(src, 'e'), "e");
113*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
114*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
115*71db0c75SAndroid Build Coastguard Worker   }
116*71db0c75SAndroid Build Coastguard Worker 
findsNullTerminatorStrrchrTest117*71db0c75SAndroid Build Coastguard Worker   void findsNullTerminator() {
118*71db0c75SAndroid Build Coastguard Worker     const char *src = "abcde";
119*71db0c75SAndroid Build Coastguard Worker 
120*71db0c75SAndroid Build Coastguard Worker     // Should return null terminator.
121*71db0c75SAndroid Build Coastguard Worker     const char *nul_terminator = Func(src, '\0');
122*71db0c75SAndroid Build Coastguard Worker     ASSERT_NE(nul_terminator, nullptr);
123*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(nul_terminator, "");
124*71db0c75SAndroid Build Coastguard Worker     // Source string should not change.
125*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(src, "abcde");
126*71db0c75SAndroid Build Coastguard Worker   }
127*71db0c75SAndroid Build Coastguard Worker 
findsLastBehindFirstNullTerminatorStrrchrTest128*71db0c75SAndroid Build Coastguard Worker   void findsLastBehindFirstNullTerminator() {
129*71db0c75SAndroid Build Coastguard Worker     static const char src[6] = {'a', 'a', '\0', 'b', '\0', 'c'};
130*71db0c75SAndroid Build Coastguard Worker     // 'b' is behind a null terminator, so should not be found.
131*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func(src, 'b'), nullptr);
132*71db0c75SAndroid Build Coastguard Worker     // Same goes for 'c'.
133*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func(src, 'c'), nullptr);
134*71db0c75SAndroid Build Coastguard Worker 
135*71db0c75SAndroid Build Coastguard Worker     // Should find the second of the two a's.
136*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(src, 'a'), "a");
137*71db0c75SAndroid Build Coastguard Worker   }
138*71db0c75SAndroid Build Coastguard Worker 
characterNotWithinStringShouldReturnNullptrStrrchrTest139*71db0c75SAndroid Build Coastguard Worker   void characterNotWithinStringShouldReturnNullptr() {
140*71db0c75SAndroid Build Coastguard Worker     // Since 'z' is not within the string, should return nullptr.
141*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("123?", 'z'), nullptr);
142*71db0c75SAndroid Build Coastguard Worker   }
143*71db0c75SAndroid Build Coastguard Worker 
shouldFindLastOfDuplicatesStrrchrTest144*71db0c75SAndroid Build Coastguard Worker   void shouldFindLastOfDuplicates() {
145*71db0c75SAndroid Build Coastguard Worker     // '1' is duplicated in the string, but it should find the last copy.
146*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func("abc1def1ghi", '1'), "1ghi");
147*71db0c75SAndroid Build Coastguard Worker 
148*71db0c75SAndroid Build Coastguard Worker     const char *dups = "XXXXX";
149*71db0c75SAndroid Build Coastguard Worker     // Should return the last occurrence of 'X'.
150*71db0c75SAndroid Build Coastguard Worker     ASSERT_STREQ(Func(dups, 'X'), "X");
151*71db0c75SAndroid Build Coastguard Worker   }
152*71db0c75SAndroid Build Coastguard Worker 
emptyStringShouldOnlyMatchNullTerminatorStrrchrTest153*71db0c75SAndroid Build Coastguard Worker   void emptyStringShouldOnlyMatchNullTerminator() {
154*71db0c75SAndroid Build Coastguard Worker     // Null terminator should match.
155*71db0c75SAndroid Build Coastguard Worker     const char empty_string[] = "";
156*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(static_cast<const char *>(Func(empty_string, '\0')),
157*71db0c75SAndroid Build Coastguard Worker               empty_string);
158*71db0c75SAndroid Build Coastguard Worker     // All other characters should not match.
159*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("", 'A'), nullptr);
160*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("", '2'), nullptr);
161*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(Func("", '*'), nullptr);
162*71db0c75SAndroid Build Coastguard Worker   }
163*71db0c75SAndroid Build Coastguard Worker };
164*71db0c75SAndroid Build Coastguard Worker 
165*71db0c75SAndroid Build Coastguard Worker #define STRCHR_TEST(name, func)                                                \
166*71db0c75SAndroid Build Coastguard Worker   using LlvmLibc##name##Test = StrchrTest<func>;                               \
167*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsFirstCharacter) { findsFirstCharacter(); } \
168*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsMiddleCharacter) {                         \
169*71db0c75SAndroid Build Coastguard Worker     findsMiddleCharacter();                                                    \
170*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
171*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsLastCharacterThatIsNotNullTerminator) {    \
172*71db0c75SAndroid Build Coastguard Worker     findsLastCharacterThatIsNotNullTerminator();                               \
173*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
174*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsNullTerminator) { findsNullTerminator(); } \
175*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, CharacterNotWithinStringShouldReturnNullptr) {  \
176*71db0c75SAndroid Build Coastguard Worker     characterNotWithinStringShouldReturnNullptr();                             \
177*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
178*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, TheSourceShouldNotChange) {                     \
179*71db0c75SAndroid Build Coastguard Worker     theSourceShouldNotChange();                                                \
180*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
181*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, ShouldFindFirstOfDuplicates) {                  \
182*71db0c75SAndroid Build Coastguard Worker     shouldFindFirstOfDuplicates();                                             \
183*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
184*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, EmptyStringShouldOnlyMatchNullTerminator) {     \
185*71db0c75SAndroid Build Coastguard Worker     emptyStringShouldOnlyMatchNullTerminator();                                \
186*71db0c75SAndroid Build Coastguard Worker   }
187*71db0c75SAndroid Build Coastguard Worker 
188*71db0c75SAndroid Build Coastguard Worker #define STRRCHR_TEST(name, func)                                               \
189*71db0c75SAndroid Build Coastguard Worker   using LlvmLibc##name##Test = StrrchrTest<func>;                              \
190*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsFirstCharacter) { findsFirstCharacter(); } \
191*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsMiddleCharacter) {                         \
192*71db0c75SAndroid Build Coastguard Worker     findsMiddleCharacter();                                                    \
193*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
194*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsLastCharacterThatIsNotNullTerminator) {    \
195*71db0c75SAndroid Build Coastguard Worker     findsLastCharacterThatIsNotNullTerminator();                               \
196*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
197*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsNullTerminator) { findsNullTerminator(); } \
198*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, FindsLastBehindFirstNullTerminator) {           \
199*71db0c75SAndroid Build Coastguard Worker     findsLastBehindFirstNullTerminator();                                      \
200*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
201*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, CharacterNotWithinStringShouldReturnNullptr) {  \
202*71db0c75SAndroid Build Coastguard Worker     characterNotWithinStringShouldReturnNullptr();                             \
203*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
204*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, ShouldFindLastOfDuplicates) {                   \
205*71db0c75SAndroid Build Coastguard Worker     shouldFindLastOfDuplicates();                                              \
206*71db0c75SAndroid Build Coastguard Worker   }                                                                            \
207*71db0c75SAndroid Build Coastguard Worker   TEST_F(LlvmLibc##name##Test, EmptyStringShouldOnlyMatchNullTerminator) {     \
208*71db0c75SAndroid Build Coastguard Worker     emptyStringShouldOnlyMatchNullTerminator();                                \
209*71db0c75SAndroid Build Coastguard Worker   }
210