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