210 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "test/UnitTest/Test.h"10 11template <auto Func> struct StrchrTest : public LIBC_NAMESPACE::testing::Test {12 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 21 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 30 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 39 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 50 void characterNotWithinStringShouldReturnNullptr() {51 // Since 'z' is not within the string, should return nullptr.52 ASSERT_EQ(Func("123?", 'z'), nullptr);53 }54 55 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 68 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 77 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 89template <auto Func> struct StrrchrTest : public LIBC_NAMESPACE::testing::Test {90 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 99 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 108 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 117 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 128 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 139 void characterNotWithinStringShouldReturnNullptr() {140 // Since 'z' is not within the string, should return nullptr.141 ASSERT_EQ(Func("123?", 'z'), nullptr);142 }143 144 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 153 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