1 | //===- llvm/unittest/ADT/SmallStringTest.cpp ------------------------------===// |
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 | // SmallString unit tests. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/ADT/SmallString.h" |
14 | #include "gtest/gtest.h" |
15 | #include <climits> |
16 | #include <cstring> |
17 | #include <stdarg.h> |
18 | |
19 | using namespace llvm; |
20 | |
21 | namespace { |
22 | |
23 | // Test fixture class |
24 | class SmallStringTest : public testing::Test { |
25 | protected: |
26 | typedef SmallString<40> StringType; |
27 | |
28 | StringType theString; |
29 | |
30 | void assertEmpty(StringType & v) { |
31 | // Size tests |
32 | EXPECT_EQ(0u, v.size()); |
33 | EXPECT_TRUE(v.empty()); |
34 | // Iterator tests |
35 | EXPECT_TRUE(v.begin() == v.end()); |
36 | } |
37 | }; |
38 | |
39 | // New string test. |
40 | TEST_F(SmallStringTest, EmptyStringTest) { |
41 | SCOPED_TRACE("EmptyStringTest" ); |
42 | assertEmpty(v&: theString); |
43 | EXPECT_TRUE(theString.rbegin() == theString.rend()); |
44 | } |
45 | |
46 | TEST_F(SmallStringTest, AssignRepeated) { |
47 | theString.assign(NumElts: 3, Elt: 'a'); |
48 | EXPECT_EQ(3u, theString.size()); |
49 | EXPECT_STREQ("aaa" , theString.c_str()); |
50 | } |
51 | |
52 | TEST_F(SmallStringTest, AssignIterPair) { |
53 | StringRef abc = "abc" ; |
54 | theString.assign(in_start: abc.begin(), in_end: abc.end()); |
55 | EXPECT_EQ(3u, theString.size()); |
56 | EXPECT_STREQ("abc" , theString.c_str()); |
57 | } |
58 | |
59 | TEST_F(SmallStringTest, AssignStringRef) { |
60 | StringRef abc = "abc" ; |
61 | theString.assign(RHS: abc); |
62 | EXPECT_EQ(3u, theString.size()); |
63 | EXPECT_STREQ("abc" , theString.c_str()); |
64 | } |
65 | |
66 | TEST_F(SmallStringTest, AssignSmallVector) { |
67 | StringRef abc = "abc" ; |
68 | SmallVector<char, 10> abcVec(abc.begin(), abc.end()); |
69 | theString.assign(RHS: abcVec); |
70 | EXPECT_EQ(3u, theString.size()); |
71 | EXPECT_STREQ("abc" , theString.c_str()); |
72 | } |
73 | |
74 | TEST_F(SmallStringTest, AssignStringRefs) { |
75 | theString.assign(Refs: {"abc" , "def" , "ghi" }); |
76 | EXPECT_EQ(9u, theString.size()); |
77 | EXPECT_STREQ("abcdefghi" , theString.c_str()); |
78 | } |
79 | |
80 | TEST_F(SmallStringTest, AppendIterPair) { |
81 | StringRef abc = "abc" ; |
82 | theString.append(in_start: abc.begin(), in_end: abc.end()); |
83 | theString.append(in_start: abc.begin(), in_end: abc.end()); |
84 | EXPECT_EQ(6u, theString.size()); |
85 | EXPECT_STREQ("abcabc" , theString.c_str()); |
86 | } |
87 | |
88 | TEST_F(SmallStringTest, AppendStringRef) { |
89 | StringRef abc = "abc" ; |
90 | theString.append(RHS: abc); |
91 | theString.append(RHS: abc); |
92 | EXPECT_EQ(6u, theString.size()); |
93 | EXPECT_STREQ("abcabc" , theString.c_str()); |
94 | } |
95 | |
96 | TEST_F(SmallStringTest, AppendSmallVector) { |
97 | StringRef abc = "abc" ; |
98 | SmallVector<char, 10> abcVec(abc.begin(), abc.end()); |
99 | theString.append(RHS: abcVec); |
100 | theString.append(RHS: abcVec); |
101 | EXPECT_EQ(6u, theString.size()); |
102 | EXPECT_STREQ("abcabc" , theString.c_str()); |
103 | } |
104 | |
105 | TEST_F(SmallStringTest, AppendStringRefs) { |
106 | theString.append(Refs: {"abc" , "def" , "ghi" }); |
107 | EXPECT_EQ(9u, theString.size()); |
108 | EXPECT_STREQ("abcdefghi" , theString.c_str()); |
109 | StringRef Jkl = "jkl" ; |
110 | std::string Mno = "mno" ; |
111 | SmallString<4> Pqr("pqr" ); |
112 | const char *Stu = "stu" ; |
113 | theString.append(Refs: {Jkl, Mno, Pqr, Stu}); |
114 | EXPECT_EQ(21u, theString.size()); |
115 | EXPECT_STREQ("abcdefghijklmnopqrstu" , theString.c_str()); |
116 | } |
117 | |
118 | TEST_F(SmallStringTest, StringRefConversion) { |
119 | StringRef abc = "abc" ; |
120 | theString.assign(in_start: abc.begin(), in_end: abc.end()); |
121 | StringRef theStringRef = theString; |
122 | EXPECT_EQ("abc" , theStringRef); |
123 | } |
124 | |
125 | TEST_F(SmallStringTest, StdStringConversion) { |
126 | StringRef abc = "abc" ; |
127 | theString.assign(in_start: abc.begin(), in_end: abc.end()); |
128 | std::string theStdString = std::string(theString); |
129 | EXPECT_EQ("abc" , theStdString); |
130 | } |
131 | |
132 | TEST_F(SmallStringTest, Substr) { |
133 | theString = "hello" ; |
134 | EXPECT_EQ("lo" , theString.substr(3)); |
135 | EXPECT_EQ("" , theString.substr(100)); |
136 | EXPECT_EQ("hello" , theString.substr(0, 100)); |
137 | EXPECT_EQ("o" , theString.substr(4, 10)); |
138 | } |
139 | |
140 | TEST_F(SmallStringTest, Slice) { |
141 | theString = "hello" ; |
142 | EXPECT_EQ("l" , theString.slice(2, 3)); |
143 | EXPECT_EQ("ell" , theString.slice(1, 4)); |
144 | EXPECT_EQ("llo" , theString.slice(2, 100)); |
145 | EXPECT_EQ("" , theString.slice(2, 1)); |
146 | EXPECT_EQ("" , theString.slice(10, 20)); |
147 | } |
148 | |
149 | TEST_F(SmallStringTest, Find) { |
150 | theString = "hello" ; |
151 | EXPECT_EQ(2U, theString.find('l')); |
152 | EXPECT_EQ(StringRef::npos, theString.find('z')); |
153 | EXPECT_EQ(StringRef::npos, theString.find("helloworld" )); |
154 | EXPECT_EQ(0U, theString.find("hello" )); |
155 | EXPECT_EQ(1U, theString.find("ello" )); |
156 | EXPECT_EQ(StringRef::npos, theString.find("zz" )); |
157 | EXPECT_EQ(2U, theString.find("ll" , 2)); |
158 | EXPECT_EQ(StringRef::npos, theString.find("ll" , 3)); |
159 | EXPECT_EQ(0U, theString.find("" )); |
160 | |
161 | EXPECT_EQ(3U, theString.rfind('l')); |
162 | EXPECT_EQ(StringRef::npos, theString.rfind('z')); |
163 | EXPECT_EQ(StringRef::npos, theString.rfind("helloworld" )); |
164 | EXPECT_EQ(0U, theString.rfind("hello" )); |
165 | EXPECT_EQ(1U, theString.rfind("ello" )); |
166 | EXPECT_EQ(StringRef::npos, theString.rfind("zz" )); |
167 | |
168 | EXPECT_EQ(2U, theString.find_first_of('l')); |
169 | EXPECT_EQ(1U, theString.find_first_of("el" )); |
170 | EXPECT_EQ(StringRef::npos, theString.find_first_of("xyz" )); |
171 | |
172 | EXPECT_EQ(1U, theString.find_first_not_of('h')); |
173 | EXPECT_EQ(4U, theString.find_first_not_of("hel" )); |
174 | EXPECT_EQ(StringRef::npos, theString.find_first_not_of("hello" )); |
175 | |
176 | theString = "hellx xello hell ello world foo bar hello" ; |
177 | EXPECT_EQ(36U, theString.find("hello" )); |
178 | EXPECT_EQ(28U, theString.find("foo" )); |
179 | EXPECT_EQ(12U, theString.find("hell" , 2)); |
180 | EXPECT_EQ(0U, theString.find("" )); |
181 | } |
182 | |
183 | TEST_F(SmallStringTest, Count) { |
184 | theString = "hello" ; |
185 | EXPECT_EQ(2U, theString.count('l')); |
186 | EXPECT_EQ(1U, theString.count('o')); |
187 | EXPECT_EQ(0U, theString.count('z')); |
188 | EXPECT_EQ(0U, theString.count("helloworld" )); |
189 | EXPECT_EQ(1U, theString.count("hello" )); |
190 | EXPECT_EQ(1U, theString.count("ello" )); |
191 | EXPECT_EQ(0U, theString.count("zz" )); |
192 | } |
193 | |
194 | TEST_F(SmallStringTest, Realloc) { |
195 | theString = "abcd" ; |
196 | theString.reserve(N: 100); |
197 | EXPECT_EQ("abcd" , theString); |
198 | unsigned const N = 100000; |
199 | theString.reserve(N); |
200 | for (unsigned i = 0; i < N - 4; ++i) |
201 | theString.push_back(Elt: 'y'); |
202 | EXPECT_EQ("abcdyyy" , theString.slice(0, 7)); |
203 | } |
204 | |
205 | TEST_F(SmallStringTest, Comparisons) { |
206 | EXPECT_GT( 0, SmallString<10>("aab" ).compare("aad" )); |
207 | EXPECT_EQ( 0, SmallString<10>("aab" ).compare("aab" )); |
208 | EXPECT_LT( 0, SmallString<10>("aab" ).compare("aaa" )); |
209 | EXPECT_GT( 0, SmallString<10>("aab" ).compare("aabb" )); |
210 | EXPECT_LT( 0, SmallString<10>("aab" ).compare("aa" )); |
211 | EXPECT_LT( 0, SmallString<10>("\xFF" ).compare("\1" )); |
212 | |
213 | EXPECT_EQ(-1, SmallString<10>("AaB" ).compare_insensitive("aAd" )); |
214 | EXPECT_EQ( 0, SmallString<10>("AaB" ).compare_insensitive("aab" )); |
215 | EXPECT_EQ( 1, SmallString<10>("AaB" ).compare_insensitive("AAA" )); |
216 | EXPECT_EQ(-1, SmallString<10>("AaB" ).compare_insensitive("aaBb" )); |
217 | EXPECT_EQ( 1, SmallString<10>("AaB" ).compare_insensitive("aA" )); |
218 | EXPECT_EQ( 1, SmallString<10>("\xFF" ).compare_insensitive("\1" )); |
219 | |
220 | EXPECT_EQ(-1, SmallString<10>("aab" ).compare_numeric("aad" )); |
221 | EXPECT_EQ( 0, SmallString<10>("aab" ).compare_numeric("aab" )); |
222 | EXPECT_EQ( 1, SmallString<10>("aab" ).compare_numeric("aaa" )); |
223 | EXPECT_EQ(-1, SmallString<10>("aab" ).compare_numeric("aabb" )); |
224 | EXPECT_EQ( 1, SmallString<10>("aab" ).compare_numeric("aa" )); |
225 | EXPECT_EQ(-1, SmallString<10>("1" ).compare_numeric("10" )); |
226 | EXPECT_EQ( 0, SmallString<10>("10" ).compare_numeric("10" )); |
227 | EXPECT_EQ( 0, SmallString<10>("10a" ).compare_numeric("10a" )); |
228 | EXPECT_EQ( 1, SmallString<10>("2" ).compare_numeric("1" )); |
229 | EXPECT_EQ( 0, SmallString<10>("llvm_v1i64_ty" ).compare_numeric("llvm_v1i64_ty" )); |
230 | EXPECT_EQ( 1, SmallString<10>("\xFF" ).compare_numeric("\1" )); |
231 | EXPECT_EQ( 1, SmallString<10>("V16" ).compare_numeric("V1_q0" )); |
232 | EXPECT_EQ(-1, SmallString<10>("V1_q0" ).compare_numeric("V16" )); |
233 | EXPECT_EQ(-1, SmallString<10>("V8_q0" ).compare_numeric("V16" )); |
234 | EXPECT_EQ( 1, SmallString<10>("V16" ).compare_numeric("V8_q0" )); |
235 | EXPECT_EQ(-1, SmallString<10>("V1_q0" ).compare_numeric("V8_q0" )); |
236 | EXPECT_EQ( 1, SmallString<10>("V8_q0" ).compare_numeric("V1_q0" )); |
237 | } |
238 | |
239 | // Check gtest prints SmallString as a string instead of a container of chars. |
240 | // The code is in utils/unittest/googletest/internal/custom/gtest-printers.h |
241 | TEST_F(SmallStringTest, GTestPrinter) { |
242 | EXPECT_EQ(R"("foo")" , ::testing::PrintToString(SmallString<1>("foo" ))); |
243 | const SmallVectorImpl<char> &ErasedSmallString = SmallString<1>("foo" ); |
244 | EXPECT_EQ(R"("foo")" , ::testing::PrintToString(ErasedSmallString)); |
245 | } |
246 | |
247 | } // namespace |
248 | |