1 /* Copyright (c) 2018 Michael Hansen
2
3 Permission is hereby granted, free of charge, to any person obtaining a
4 copy of this software and associated documentation files (the "Software"),
5 to deal in the Software without restriction, including without limitation
6 the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 and/or sell copies of the Software, and to permit persons to whom the
8 Software is furnished to do so, subject to the following conditions:
9
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 DEALINGS IN THE SOFTWARE. */
20
21 #include "st_string.h"
22
23 #include <gtest/gtest.h>
24
25 namespace ST
26 {
27 // Teach GTest how to print an ST::buffer
PrintTo(const ST::char_buffer & str,std::ostream * os)28 static void PrintTo(const ST::char_buffer &str, std::ostream *os)
29 {
30 *os << "ST::char_buffer{\"" << str.data() << "\"}";
31 }
32
PrintTo(const ST::wchar_buffer & str,std::ostream * os)33 static void PrintTo(const ST::wchar_buffer &str, std::ostream *os)
34 {
35 ST::string u8str = str;
36 *os << "ST::wchar_buffer{\"" << u8str.c_str() << "\"}";
37 }
38
PrintTo(const ST::utf16_buffer & str,std::ostream * os)39 static void PrintTo(const ST::utf16_buffer &str, std::ostream *os)
40 {
41 ST::string u8str = str;
42 *os << "ST::utf16_buffer{\"" << u8str.c_str() << "\"}";
43 }
44
PrintTo(const ST::utf32_buffer & str,std::ostream * os)45 static void PrintTo(const ST::utf32_buffer &str, std::ostream *os)
46 {
47 ST::string u8str = str;
48 *os << "ST::utf32_buffer{\"" << u8str.c_str() << "\"}";
49 }
50 }
51
52 /* Utility for comparing char16_t/char32_t buffers */
53 template <typename char_T>
T_strcmp(const char_T * left,const char_T * right)54 static int T_strcmp(const char_T *left, const char_T *right)
55 {
56 for ( ;; ) {
57 if (*left != *right)
58 return *left - *right;
59 if (*left == 0)
60 return 0;
61
62 ++left;
63 ++right;
64 }
65 }
66
TEST(char_buffer,helpers)67 TEST(char_buffer, helpers)
68 {
69 /* Ensure the utilities for testing the module function properly */
70 EXPECT_EQ(0, T_strcmp("abc", "abc"));
71 EXPECT_LT(0, T_strcmp("abc", "aba"));
72 EXPECT_GT(0, T_strcmp("abc", "abe"));
73 EXPECT_LT(0, T_strcmp("abc", "ab"));
74 EXPECT_GT(0, T_strcmp("abc", "abcd"));
75 EXPECT_EQ(0, T_strcmp("", ""));
76 EXPECT_GT(0, T_strcmp("", "a"));
77 EXPECT_LT(0, T_strcmp("a", ""));
78 }
79
TEST(char_buffer,utility)80 TEST(char_buffer, utility)
81 {
82 // Literal constructors
83 EXPECT_EQ(ST::char_buffer(), ST_CHAR_LITERAL(""));
84 EXPECT_EQ(ST::wchar_buffer(), ST_WCHAR_LITERAL(""));
85 EXPECT_EQ(ST::utf16_buffer(), ST_UTF16_LITERAL(""));
86 EXPECT_EQ(ST::utf32_buffer(), ST_UTF32_LITERAL(""));
87 EXPECT_EQ(ST::char_buffer("abc", 3), ST_CHAR_LITERAL("abc"));
88 EXPECT_EQ(ST::wchar_buffer(L"abc", 3), ST_WCHAR_LITERAL("abc"));
89 EXPECT_EQ(ST::utf16_buffer(u"abc", 3), ST_UTF16_LITERAL("abc"));
90 EXPECT_EQ(ST::utf32_buffer(U"abc", 3), ST_UTF32_LITERAL("abc"));
91
92 EXPECT_EQ(0U, ST::char_buffer().size());
93 EXPECT_TRUE(ST::char_buffer().empty());
94 EXPECT_EQ(0U, ST::wchar_buffer().size());
95 EXPECT_TRUE(ST::wchar_buffer().empty());
96 EXPECT_EQ(0U, ST::utf16_buffer().size());
97 EXPECT_TRUE(ST::utf16_buffer().empty());
98 EXPECT_EQ(0U, ST::utf32_buffer().size());
99 EXPECT_TRUE(ST::utf32_buffer().empty());
100 }
101
TEST(char_buffer,stack_construction)102 TEST(char_buffer, stack_construction)
103 {
104 // If these change, this test may need to be updated to match
105 ASSERT_EQ(16, ST_MAX_SSO_LENGTH);
106 ASSERT_EQ(48, ST_MAX_SSO_SIZE);
107
108 char empty[] = {0};
109 wchar_t emptyw[] = {0};
110 char16_t empty16[] = {0};
111 char32_t empty32[] = {0};
112
113 // Stack allocated
114 char shortstr[] = "Short";
115 wchar_t shortw[] = L"Short";
116 char16_t short16[] = {'S', 'h', 'o', 'r', 't', 0};
117 char32_t short32[] = {'S', 'h', 'o', 'r', 't', 0};
118
119 // Heap allocated
120 char longstr[] = "0123456789abcdefghij";
121 wchar_t longw[] = L"0123456789abcdefghij";
122 char16_t long16[] = {'0','1','2','3','4','5','6','7','8','9',
123 'a','b','c','d','e','f','g','h','i','j',0};
124 char32_t long32[] = {'0','1','2','3','4','5','6','7','8','9',
125 'a','b','c','d','e','f','g','h','i','j',0};
126
127 ST::char_buffer cb_empty(empty, 0);
128 EXPECT_EQ(0, T_strcmp(cb_empty.data(), empty));
129 EXPECT_EQ(0U, cb_empty.size());
130 EXPECT_TRUE(cb_empty.empty());
131 ST::wchar_buffer wcb_empty(emptyw, 0);
132 EXPECT_EQ(0, T_strcmp(wcb_empty.data(), emptyw));
133 EXPECT_EQ(0U, wcb_empty.size());
134 EXPECT_TRUE(wcb_empty.empty());
135 ST::utf16_buffer cb16_empty(empty16, 0);
136 EXPECT_EQ(0, T_strcmp(cb16_empty.data(), empty16));
137 EXPECT_EQ(0U, cb16_empty.size());
138 EXPECT_TRUE(cb16_empty.empty());
139 ST::utf32_buffer cb32_empty(empty32, 0);
140 EXPECT_EQ(0, T_strcmp(cb32_empty.data(), empty32));
141 EXPECT_EQ(0U, cb32_empty.size());
142 EXPECT_TRUE(cb32_empty.empty());
143
144 ST::char_buffer cb_short(shortstr, 5);
145 EXPECT_EQ(0, T_strcmp(cb_short.data(), shortstr));
146 EXPECT_EQ(5U, cb_short.size());
147 EXPECT_FALSE(cb_short.empty());
148 ST::wchar_buffer wcb_short(shortw, 5);
149 EXPECT_EQ(0, T_strcmp(wcb_short.data(), shortw));
150 EXPECT_EQ(5U, wcb_short.size());
151 EXPECT_FALSE(wcb_short.empty());
152 ST::utf16_buffer cb16_short(short16, 5);
153 EXPECT_EQ(0, T_strcmp(cb16_short.data(), short16));
154 EXPECT_EQ(5U, cb16_short.size());
155 EXPECT_FALSE(cb_short.empty());
156 ST::utf32_buffer cb32_short(short32, 5);
157 EXPECT_EQ(0, T_strcmp(cb32_short.data(), short32));
158 EXPECT_EQ(5U, cb32_short.size());
159 EXPECT_FALSE(cb32_short.empty());
160
161 ST::char_buffer cb_long(longstr, 20);
162 EXPECT_EQ(0, T_strcmp(cb_long.data(), longstr));
163 EXPECT_EQ(20U, cb_long.size());
164 EXPECT_FALSE(cb_long.empty());
165 ST::wchar_buffer wcb_long(longw, 20);
166 EXPECT_EQ(0, T_strcmp(wcb_long.data(), longw));
167 EXPECT_EQ(20U, wcb_long.size());
168 EXPECT_FALSE(wcb_long.empty());
169 ST::utf16_buffer cb16_long(long16, 20);
170 EXPECT_EQ(0, T_strcmp(cb16_long.data(), long16));
171 EXPECT_EQ(20U, cb16_long.size());
172 EXPECT_FALSE(cb_long.empty());
173 ST::utf32_buffer cb32_long(long32, 20);
174 EXPECT_EQ(0, T_strcmp(cb32_long.data(), long32));
175 EXPECT_EQ(20U, cb32_long.size());
176 EXPECT_FALSE(cb32_long.empty());
177 }
178
179 // Only testing char and wchar_t for simplicity on compilers that
180 // don't support utf-16 and utf-32 literals yet
TEST(char_buffer,copy)181 TEST(char_buffer, copy)
182 {
183 // If these change, this test may need to be updated to match
184 ASSERT_EQ(16, ST_MAX_SSO_LENGTH);
185 ASSERT_EQ(48, ST_MAX_SSO_SIZE);
186
187 ST::char_buffer cb1("Test", 4);
188 ST::wchar_buffer wcb1(L"Test", 4);
189
190 ST::char_buffer dest(cb1);
191 EXPECT_EQ(0, T_strcmp(dest.data(), "Test"));
192 EXPECT_EQ(4U, dest.size());
193 ST::wchar_buffer wdest(wcb1);
194 EXPECT_EQ(0, T_strcmp(wdest.data(), L"Test"));
195 EXPECT_EQ(4U, wdest.size());
196
197 ST::char_buffer cb2("operator=", 9);
198 ST::wchar_buffer wcb2(L"operator=", 9);
199
200 dest = cb2;
201 EXPECT_EQ(0, T_strcmp(dest.data(), "operator="));
202 EXPECT_EQ(9U, dest.size());
203 wdest = wcb2;
204 EXPECT_EQ(0, T_strcmp(wdest.data(), L"operator="));
205 EXPECT_EQ(9U, wdest.size());
206
207 ST::char_buffer cb3("0123456789abcdefghij", 20);
208 ST::wchar_buffer wcb3(L"0123456789abcdefghij", 20);
209
210 ST::char_buffer dest2(cb3);
211 EXPECT_EQ(0, T_strcmp(dest2.data(), "0123456789abcdefghij"));
212 EXPECT_EQ(20U, dest2.size());
213 ST::wchar_buffer wdest2(wcb3);
214 EXPECT_EQ(0, T_strcmp(wdest2.data(), L"0123456789abcdefghij"));
215 EXPECT_EQ(20U, wdest2.size());
216
217 ST::char_buffer cb4("9876543210zyxwvutsrqponm", 24);
218 ST::wchar_buffer wcb4(L"9876543210zyxwvutsrqponm", 24);
219
220 dest2 = cb4;
221 EXPECT_EQ(0, T_strcmp(dest2.data(), "9876543210zyxwvutsrqponm"));
222 EXPECT_EQ(24U, dest2.size());
223 wdest2 = wcb4;
224 EXPECT_EQ(0, T_strcmp(wdest2.data(), L"9876543210zyxwvutsrqponm"));
225 EXPECT_EQ(24U, wdest2.size());
226 }
227
TEST(char_buffer,move)228 TEST(char_buffer, move)
229 {
230 // If these change, this test may need to be updated to match
231 ASSERT_EQ(16, ST_MAX_SSO_LENGTH);
232 ASSERT_EQ(48, ST_MAX_SSO_SIZE);
233
234 ST::char_buffer cb1("Test", 4);
235 ST::wchar_buffer wcb1(L"Test", 4);
236
237 ST::char_buffer dest(std::move(cb1));
238 EXPECT_EQ(0, T_strcmp(dest.data(), "Test"));
239 EXPECT_EQ(4U, dest.size());
240 ST::wchar_buffer wdest(std::move(wcb1));
241 EXPECT_EQ(0, T_strcmp(wdest.data(), L"Test"));
242 EXPECT_EQ(4U, wdest.size());
243
244 ST::char_buffer cb2("operator=", 9);
245 ST::wchar_buffer wcb2(L"operator=", 9);
246
247 dest = std::move(cb2);
248 EXPECT_EQ(0, T_strcmp(dest.data(), "operator="));
249 EXPECT_EQ(9U, dest.size());
250 wdest = std::move(wcb2);
251 EXPECT_EQ(0, T_strcmp(wdest.data(), L"operator="));
252 EXPECT_EQ(9U, wdest.size());
253
254 ST::char_buffer cb3("0123456789abcdefghij", 20);
255 ST::wchar_buffer wcb3(L"0123456789abcdefghij", 20);
256
257 ST::char_buffer dest2(std::move(cb3));
258 EXPECT_EQ(0, T_strcmp(dest2.data(), "0123456789abcdefghij"));
259 EXPECT_EQ(20U, dest2.size());
260 ST::wchar_buffer wdest2(std::move(wcb3));
261 EXPECT_EQ(0, T_strcmp(wdest2.data(), L"0123456789abcdefghij"));
262 EXPECT_EQ(20U, wdest2.size());
263
264 ST::char_buffer cb4("9876543210zyxwvutsrqponm", 24);
265 ST::wchar_buffer wcb4(L"9876543210zyxwvutsrqponm", 24);
266
267 dest2 = std::move(cb4);
268 EXPECT_EQ(0, T_strcmp(dest2.data(), "9876543210zyxwvutsrqponm"));
269 EXPECT_EQ(24U, dest2.size());
270 wdest2 = std::move(wcb4);
271 EXPECT_EQ(0, T_strcmp(wdest2.data(), L"9876543210zyxwvutsrqponm"));
272 EXPECT_EQ(24U, wdest2.size());
273 }
274
275 #if defined(__clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ > 5))
276 # pragma GCC diagnostic push
277 # pragma GCC diagnostic ignored "-Wself-move"
278 # if defined(__clang__) && (__clang_major__ > 6)
279 # pragma GCC diagnostic ignored "-Wself-assign-overloaded"
280 # endif
281 #endif
282
TEST(char_buffer,self_assign)283 TEST(char_buffer, self_assign)
284 {
285 // If this changes, this test may need to be updated to match
286 ASSERT_EQ(16, ST_MAX_SSO_LENGTH);
287
288 ST::char_buffer sbuf;
289 sbuf = sbuf;
290 EXPECT_EQ(0, T_strcmp(sbuf.data(), ""));
291
292 ST::char_buffer shortbuf("0123456789", 10);
293 sbuf = shortbuf;
294 EXPECT_EQ(0, T_strcmp(sbuf.data(), "0123456789"));
295 sbuf = sbuf;
296 EXPECT_EQ(0, T_strcmp(sbuf.data(), "0123456789"));
297 sbuf = std::move(sbuf);
298 // Content not guaranteed after self-move
299
300 ST::char_buffer longbuf("0123456789abcdefghij", 20);
301 sbuf = longbuf;
302 EXPECT_EQ(0, T_strcmp(sbuf.data(), "0123456789abcdefghij"));
303 sbuf = sbuf;
304 EXPECT_EQ(0, T_strcmp(sbuf.data(), "0123456789abcdefghij"));
305 sbuf = std::move(sbuf);
306 // Content not guaranteed after self-move
307 }
308
309 #if defined(__clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ > 5))
310 # pragma GCC diagnostic pop
311 #endif
312
TEST(char_buffer,compare)313 TEST(char_buffer, compare)
314 {
315 // Same length, chars
316 EXPECT_EQ(ST::char_buffer("abc", 3), ST::char_buffer("abc", 3));
317 EXPECT_NE(ST::char_buffer("abc", 3), ST::char_buffer("abd", 3));
318 EXPECT_NE(ST::char_buffer("abc", 3), ST::char_buffer("abb", 3));
319 EXPECT_NE(ST::char_buffer("abC", 3), ST::char_buffer("abc", 3));
320 EXPECT_NE(ST::char_buffer("Abc", 3), ST::char_buffer("abc", 3));
321 EXPECT_EQ(ST::char_buffer("", 0), ST::char_buffer());
322
323 // Same length, wchars
324 EXPECT_EQ(ST::wchar_buffer(L"abc", 3), ST::wchar_buffer(L"abc", 3));
325 EXPECT_NE(ST::wchar_buffer(L"abc", 3), ST::wchar_buffer(L"abd", 3));
326 EXPECT_NE(ST::wchar_buffer(L"abc", 3), ST::wchar_buffer(L"abb", 3));
327 EXPECT_NE(ST::wchar_buffer(L"abC", 3), ST::wchar_buffer(L"abc", 3));
328 EXPECT_NE(ST::wchar_buffer(L"Abc", 3), ST::wchar_buffer(L"abc", 3));
329 EXPECT_EQ(ST::wchar_buffer(L"", 0), ST::wchar_buffer());
330
331 // Mismatched length, chars
332 EXPECT_NE(ST::char_buffer("abc", 3), ST::char_buffer("ab", 2));
333 EXPECT_NE(ST::char_buffer("abc", 3), ST::char_buffer("abcd", 4));
334 EXPECT_NE(ST::char_buffer("abc", 3), ST::char_buffer("", 0));
335 EXPECT_NE(ST::char_buffer(), ST::char_buffer("abc", 3));
336
337 // Mismatched length, wchars
338 EXPECT_NE(ST::wchar_buffer(L"abc", 3), ST::wchar_buffer(L"ab", 2));
339 EXPECT_NE(ST::wchar_buffer(L"abc", 3), ST::wchar_buffer(L"abcd", 4));
340 EXPECT_NE(ST::wchar_buffer(L"abc", 3), ST::wchar_buffer(L"", 0));
341 EXPECT_NE(ST::wchar_buffer(), ST::wchar_buffer(L"abc", 3));
342 }
343
TEST(char_buffer,udls)344 TEST(char_buffer, udls)
345 {
346 using namespace ST::literals;
347
348 // Only need to test the UDL usage -- the rest is covered above
349 EXPECT_EQ(ST_CHAR_LITERAL(""), ""_stbuf);
350 EXPECT_EQ(ST_CHAR_LITERAL("Test"), "Test"_stbuf);
351 EXPECT_EQ(ST_WCHAR_LITERAL("Test"), L"Test"_stbuf);
352 EXPECT_EQ(ST_UTF16_LITERAL("Test"), u"Test"_stbuf);
353 EXPECT_EQ(ST_UTF32_LITERAL("Test"), U"Test"_stbuf);
354 #ifdef ST_HAVE_CXX20_CHAR8_TYPES
355 EXPECT_EQ(ST_CHAR_LITERAL("Test"), u8"Test"_stbuf);
356 #endif
357 }
358