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