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