• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     ASSERT_STREQ(Func(src, '\0'), "");
44     // Source string should not change.
45     ASSERT_STREQ(src, "abcde");
46   }
47 
characterNotWithinStringShouldReturnNullptrStrchrTest48   void characterNotWithinStringShouldReturnNullptr() {
49     // Since 'z' is not within the string, should return nullptr.
50     ASSERT_STREQ(Func("123?", 'z'), nullptr);
51   }
52 
theSourceShouldNotChangeStrchrTest53   void theSourceShouldNotChange() {
54     const char *src = "abcde";
55     // When the character is found, the source string should not change.
56     Func(src, 'd');
57     ASSERT_STREQ(src, "abcde");
58     // Same case for when the character is not found.
59     Func(src, 'z');
60     ASSERT_STREQ(src, "abcde");
61     // Same case for when looking for nullptr.
62     Func(src, '\0');
63     ASSERT_STREQ(src, "abcde");
64   }
65 
shouldFindFirstOfDuplicatesStrchrTest66   void shouldFindFirstOfDuplicates() {
67     // '1' is duplicated in the string, but it should find the first copy.
68     ASSERT_STREQ(Func("abc1def1ghi", '1'), "1def1ghi");
69 
70     const char *dups = "XXXXX";
71     // Should return original string since 'X' is the first character.
72     ASSERT_STREQ(Func(dups, 'X'), dups);
73   }
74 
emptyStringShouldOnlyMatchNullTerminatorStrchrTest75   void emptyStringShouldOnlyMatchNullTerminator() {
76     // Null terminator should match.
77     ASSERT_STREQ(Func("", '\0'), "");
78     // All other characters should not match.
79     ASSERT_STREQ(Func("", 'Z'), nullptr);
80     ASSERT_STREQ(Func("", '3'), nullptr);
81     ASSERT_STREQ(Func("", '*'), nullptr);
82   }
83 };
84 
85 template <auto Func> struct StrrchrTest : public LIBC_NAMESPACE::testing::Test {
findsFirstCharacterStrrchrTest86   void findsFirstCharacter() {
87     const char *src = "abcde";
88 
89     // Should return original string since 'a' is the first character.
90     ASSERT_STREQ(Func(src, 'a'), "abcde");
91     // Source string should not change.
92     ASSERT_STREQ(src, "abcde");
93   }
94 
findsMiddleCharacterStrrchrTest95   void findsMiddleCharacter() {
96     const char *src = "abcde";
97 
98     // Should return characters after (and including) 'c'.
99     ASSERT_STREQ(Func(src, 'c'), "cde");
100     // Source string should not change.
101     ASSERT_STREQ(src, "abcde");
102   }
103 
findsLastCharacterThatIsNotNullTerminatorStrrchrTest104   void findsLastCharacterThatIsNotNullTerminator() {
105     const char *src = "abcde";
106 
107     // Should return 'e' and null-terminator.
108     ASSERT_STREQ(Func(src, 'e'), "e");
109     // Source string should not change.
110     ASSERT_STREQ(src, "abcde");
111   }
112 
findsNullTerminatorStrrchrTest113   void findsNullTerminator() {
114     const char *src = "abcde";
115 
116     // Should return null terminator.
117     ASSERT_STREQ(Func(src, '\0'), "");
118     // Source string should not change.
119     ASSERT_STREQ(src, "abcde");
120   }
121 
findsLastBehindFirstNullTerminatorStrrchrTest122   void findsLastBehindFirstNullTerminator() {
123     static const char src[6] = {'a', 'a', '\0', 'b', '\0', 'c'};
124     // 'b' is behind a null terminator, so should not be found.
125     ASSERT_STREQ(Func(src, 'b'), nullptr);
126     // Same goes for 'c'.
127     ASSERT_STREQ(Func(src, 'c'), nullptr);
128 
129     // Should find the second of the two a's.
130     ASSERT_STREQ(Func(src, 'a'), "a");
131   }
132 
characterNotWithinStringShouldReturnNullptrStrrchrTest133   void characterNotWithinStringShouldReturnNullptr() {
134     // Since 'z' is not within the string, should return nullptr.
135     ASSERT_STREQ(Func("123?", 'z'), nullptr);
136   }
137 
shouldFindLastOfDuplicatesStrrchrTest138   void shouldFindLastOfDuplicates() {
139     // '1' is duplicated in the string, but it should find the last copy.
140     ASSERT_STREQ(Func("abc1def1ghi", '1'), "1ghi");
141 
142     const char *dups = "XXXXX";
143     // Should return the last occurrence of 'X'.
144     ASSERT_STREQ(Func(dups, 'X'), "X");
145   }
146 
emptyStringShouldOnlyMatchNullTerminatorStrrchrTest147   void emptyStringShouldOnlyMatchNullTerminator() {
148     // Null terminator should match.
149     ASSERT_STREQ(Func("", '\0'), "");
150     // All other characters should not match.
151     ASSERT_STREQ(Func("", 'A'), nullptr);
152     ASSERT_STREQ(Func("", '2'), nullptr);
153     ASSERT_STREQ(Func("", '*'), nullptr);
154   }
155 };
156 
157 #define STRCHR_TEST(name, func)                                                \
158   using LlvmLibc##name##Test = StrchrTest<func>;                               \
159   TEST_F(LlvmLibc##name##Test, FindsFirstCharacter) { findsFirstCharacter(); } \
160   TEST_F(LlvmLibc##name##Test, FindsMiddleCharacter) {                         \
161     findsMiddleCharacter();                                                    \
162   }                                                                            \
163   TEST_F(LlvmLibc##name##Test, FindsLastCharacterThatIsNotNullTerminator) {    \
164     findsLastCharacterThatIsNotNullTerminator();                               \
165   }                                                                            \
166   TEST_F(LlvmLibc##name##Test, FindsNullTerminator) { findsNullTerminator(); } \
167   TEST_F(LlvmLibc##name##Test, CharacterNotWithinStringShouldReturnNullptr) {  \
168     characterNotWithinStringShouldReturnNullptr();                             \
169   }                                                                            \
170   TEST_F(LlvmLibc##name##Test, TheSourceShouldNotChange) {                     \
171     theSourceShouldNotChange();                                                \
172   }                                                                            \
173   TEST_F(LlvmLibc##name##Test, ShouldFindFirstOfDuplicates) {                  \
174     shouldFindFirstOfDuplicates();                                             \
175   }                                                                            \
176   TEST_F(LlvmLibc##name##Test, EmptyStringShouldOnlyMatchNullTerminator) {     \
177     emptyStringShouldOnlyMatchNullTerminator();                                \
178   }
179 
180 #define STRRCHR_TEST(name, func)                                               \
181   using LlvmLibc##name##Test = StrrchrTest<func>;                              \
182   TEST_F(LlvmLibc##name##Test, FindsFirstCharacter) { findsFirstCharacter(); } \
183   TEST_F(LlvmLibc##name##Test, FindsMiddleCharacter) {                         \
184     findsMiddleCharacter();                                                    \
185   }                                                                            \
186   TEST_F(LlvmLibc##name##Test, FindsLastCharacterThatIsNotNullTerminator) {    \
187     findsLastCharacterThatIsNotNullTerminator();                               \
188   }                                                                            \
189   TEST_F(LlvmLibc##name##Test, FindsNullTerminator) { findsNullTerminator(); } \
190   TEST_F(LlvmLibc##name##Test, FindsLastBehindFirstNullTerminator) {           \
191     findsLastBehindFirstNullTerminator();                                      \
192   }                                                                            \
193   TEST_F(LlvmLibc##name##Test, CharacterNotWithinStringShouldReturnNullptr) {  \
194     characterNotWithinStringShouldReturnNullptr();                             \
195   }                                                                            \
196   TEST_F(LlvmLibc##name##Test, ShouldFindLastOfDuplicates) {                   \
197     shouldFindLastOfDuplicates();                                              \
198   }                                                                            \
199   TEST_F(LlvmLibc##name##Test, EmptyStringShouldOnlyMatchNullTerminator) {     \
200     emptyStringShouldOnlyMatchNullTerminator();                                \
201   }
202