1// Copyright 2014 The Android Open Source Project
2//
3// This software is licensed under the terms of the GNU General Public
4// License version 2, as published by the Free Software Foundation, and
5// may be copied, distributed, and modified under those terms.
6//
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10// GNU General Public License for more details.
11
12#include "android/base/String.h"
13
14#include "android/base/StringView.h"
15
16#include <gtest/gtest.h>
17
18namespace android {
19namespace base {
20
21TEST(String, DefaultConstructor) {
22    String s;
23    EXPECT_EQ(0U, s.size());
24    EXPECT_TRUE(s.empty());
25}
26
27TEST(String, SimpleConstructor) {
28    static const char kString[] = "hello you";
29    const size_t kStringLen = sizeof(kString) - 1U;
30
31    String s(kString);
32    EXPECT_NE(kString, s.c_str());
33    EXPECT_EQ(kStringLen, s.size());
34    EXPECT_FALSE(s.empty());
35    EXPECT_STREQ(kString, s.c_str());
36}
37
38TEST(String, SimpleConstructorWithLongString) {
39    static const char kString[] =
40            "this is a long string that should exceed the "
41            "small-string-optimization capacity";
42    const size_t kStringLen = sizeof(kString) - 1U;
43
44    String s(kString);
45    EXPECT_NE(kString, s.c_str());
46    EXPECT_EQ(kStringLen, s.size());
47    EXPECT_FALSE(s.empty());
48    EXPECT_STREQ(kString, s.c_str());
49}
50
51TEST(String, CopyConstructor) {
52    String s1("Hello World!");
53    String s2(s1);
54    EXPECT_EQ(s1.size(), s2.size());
55    EXPECT_STREQ(s1.c_str(), s2.c_str());
56}
57
58TEST(String, ConstructorFromStringView) {
59    StringView view("Hello Cowboys");
60    String s(view);
61    EXPECT_NE(view.str(), s.c_str());
62    EXPECT_EQ(view.size(), s.size());
63    EXPECT_STREQ(view.str(), s.c_str());
64}
65
66TEST(String, ConstructorWithCountAndFill) {
67    const size_t kCount = 1024;
68    const char kFill = 0x42;
69
70    String s(kCount, kFill);
71    EXPECT_EQ(kCount, s.size());
72    for (size_t n = 0; n < kCount; ++n)
73        EXPECT_EQ(kFill, s[n]);
74}
75
76TEST(String, empty) {
77    String s1("");
78    EXPECT_TRUE(s1.empty());
79
80    String s2("foo");
81    EXPECT_FALSE(s2.empty());
82}
83
84TEST(String, size) {
85    const size_t kCount = 4096;
86    String s;
87    for (size_t n = 0; n < kCount; ++n) {
88        EXPECT_EQ(n, s.size());
89        s += 'x';
90    }
91    EXPECT_EQ(kCount, s.size());
92}
93
94TEST(String, clear) {
95    String s("foo bar");
96    EXPECT_FALSE(s.empty());
97    s.clear();
98    EXPECT_TRUE(s.empty());
99    EXPECT_EQ(0U, s.size());
100}
101
102TEST(String, IndexedAccess) {
103    String s("foobar");
104    EXPECT_EQ('f', s[0]);
105    EXPECT_EQ('o', s[1]);
106    EXPECT_EQ('o', s[2]);
107    EXPECT_EQ('b', s[3]);
108    EXPECT_EQ('a', s[4]);
109    EXPECT_EQ('r', s[5]);
110    EXPECT_EQ('\0', s[6]);
111}
112
113TEST(String, AssignOperatorWithCString) {
114    static const char kString[] = "Hello 10234";
115    const size_t kStringLen = sizeof(kString) - 1U;
116
117    String s;
118    s = kString;
119    EXPECT_NE(kString, s.c_str());
120    EXPECT_EQ(kStringLen, s.size());
121    EXPECT_STREQ(kString, s.c_str());
122}
123
124TEST(String, AssignOperatorWithOtherString) {
125    String s0("A fish named Wanda");
126    String s;
127    s = s0;
128    EXPECT_EQ(s0.size(), s.size());
129    EXPECT_STREQ(s0.c_str(), s.c_str());
130}
131
132TEST(String, AssignOperatorWithStringView) {
133    StringView v0("What a beautiful world");
134    String s;
135    s = v0;
136    EXPECT_EQ(v0.size(), s.size());
137    EXPECT_STREQ(v0.str(), s.c_str());
138}
139
140TEST(String, AssignOperatorWithChar) {
141    String s;
142    s = 'f';
143    EXPECT_EQ(1U, s.size());
144    EXPECT_EQ('f', s[0]);
145}
146
147TEST(String, assignWithCString) {
148    static const char kString[] = "Hello";
149    const size_t kStringLen = sizeof(kString) - 1U;
150
151    String  s;
152    s.assign(kString);
153    EXPECT_EQ(kStringLen, s.size());
154    EXPECT_STREQ(kString, s.c_str());
155}
156
157TEST(String, assignWithString) {
158    String s0("Input string");
159    String s;
160    s.assign(s0);
161    EXPECT_EQ(s0.size(), s.size());
162    EXPECT_STREQ(s0.c_str(), s.c_str());
163}
164
165TEST(String, assignWithStringAndLen) {
166    static const char kString[] = "Who you're gonna call?";
167    const size_t kStringLen = sizeof(kString) - 1U;
168
169    String s;
170    s.assign(kString, kStringLen);
171    EXPECT_NE(kString, s.c_str());
172    EXPECT_EQ(kStringLen, s.size());
173    EXPECT_STREQ(kString, s.c_str());
174}
175
176TEST(String, assignWithCountAndFill) {
177    const size_t kCount = 1024;
178    const char kFill = '\x7f';
179    String s;
180    s.assign(kCount, kFill);
181    EXPECT_EQ(kCount, s.size());
182    for (size_t n = 0; n < kCount; ++n) {
183        EXPECT_EQ(kFill, s[n]) << "At index " << n;
184    }
185}
186
187TEST(String, assignWithStringView) {
188    StringView v0("Input string view");
189    String s;
190    s.assign(v0);
191    EXPECT_EQ(v0.size(), s.size());
192    EXPECT_STREQ(v0.str(), s.c_str());
193}
194
195TEST(String, assignWithChar) {
196    String s;
197    s.assign('f');
198    EXPECT_EQ(1U, s.size());
199    EXPECT_STREQ("f", s.c_str());
200}
201
202typedef struct {
203    const char* s1;
204    const char* s2;
205    int expected;
206} Comparison;
207
208static const Comparison kComparisons[] = {
209    { "", "", 0 },
210    { "", "foo", -1 },
211    { "foo", "", +1 },
212    { "foo", "zoo", -1 },
213    { "foo", "foo", 0 },
214    { "foo", "fo", +1 },
215    { "foo", "fooo", -1 },
216    { "foo", "fop", -1 },
217    { "foo", "fon", +1 },
218};
219
220#define ARRAY_SIZE(x)  (sizeof(x)/sizeof(x[0]))
221
222TEST(String, compareWithCString) {
223    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
224        const Comparison& comp = kComparisons[n];
225        String s(comp.s1);
226        EXPECT_EQ(comp.expected, s.compare(comp.s2))
227                << "Comparing '" << comp.s1 << "' with '"
228                << comp.s2 << "'";
229    }
230}
231
232TEST(String, compareWithCStringWithLen) {
233    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
234        const Comparison& comp = kComparisons[n];
235        String s(comp.s1);
236        size_t len2 = ::strlen(comp.s2);
237        EXPECT_EQ(comp.expected, s.compare(comp.s2, len2))
238                << "Comparing '" << comp.s1 << "' with '"
239                << comp.s2 << "'";
240    }
241}
242
243
244TEST(String, compareWithString) {
245    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
246        const Comparison& comp = kComparisons[n];
247        String s1(comp.s1);
248        String s2(comp.s2);
249        EXPECT_EQ(comp.expected, s1.compare(s2))
250                << "Comparing '" << comp.s1 << "' with '"
251                << comp.s2 << "'";
252    }
253}
254
255TEST(String, compareWithStringView) {
256    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
257        const Comparison& comp = kComparisons[n];
258        String s1(comp.s1);
259        StringView s2(comp.s2);
260        EXPECT_EQ(comp.expected, s1.compare(s2))
261                << "Comparing '" << comp.s1 << "' with '"
262                << comp.s2 << "'";
263    }
264}
265
266TEST(String, equalsWithCString) {
267    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
268        const Comparison& comp = kComparisons[n];
269        String s(comp.s1);
270        EXPECT_EQ(!comp.expected, s.equals(comp.s2))
271                << "Comparing '" << comp.s1 << "' with '"
272                << comp.s2 << "'";
273    }
274}
275
276TEST(String, equalsWithCStringWithLen) {
277    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
278        const Comparison& comp = kComparisons[n];
279        String s(comp.s1);
280        size_t len2 = ::strlen(comp.s2);
281        EXPECT_EQ(!comp.expected, s.equals(comp.s2, len2))
282                << "Comparing '" << comp.s1 << "' with '"
283                << comp.s2 << "'";
284    }
285}
286
287
288TEST(String, equalsWithString) {
289    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
290        const Comparison& comp = kComparisons[n];
291        String s1(comp.s1);
292        String s2(comp.s2);
293        EXPECT_EQ(!comp.expected, s1.equals(s2))
294                << "Comparing '" << comp.s1 << "' with '"
295                << comp.s2 << "'";
296    }
297}
298
299TEST(String, equalsWithStringView) {
300    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
301        const Comparison& comp = kComparisons[n];
302        String s1(comp.s1);
303        StringView s2(comp.s2);
304        EXPECT_EQ(!comp.expected, s1.equals(s2))
305                << "Comparing '" << comp.s1 << "' with '"
306                << comp.s2 << "'";
307    }
308}
309
310TEST(String, EqualsOperatorWithCString) {
311    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
312        const Comparison& comp = kComparisons[n];
313        String s(comp.s1);
314        EXPECT_EQ(!comp.expected, s == comp.s2)
315                << "Comparing '" << comp.s1 << "' with '"
316                << comp.s2 << "'";
317    }
318}
319
320TEST(String, EqualsOperatorWithString) {
321    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
322        const Comparison& comp = kComparisons[n];
323        String s1(comp.s1);
324        String s2(comp.s2);
325        EXPECT_EQ(!comp.expected, s1 == s2)
326                << "Comparing '" << comp.s1 << "' with '"
327                << comp.s2 << "'";
328    }
329}
330
331TEST(String, EqualsOperatorWithStringView) {
332    for (size_t n = 0; n < ARRAY_SIZE(kComparisons); ++n) {
333        const Comparison& comp = kComparisons[n];
334        String s1(comp.s1);
335        StringView s2(comp.s2);
336        EXPECT_EQ(!comp.expected, s1 == s2)
337                << "Comparing '" << comp.s1 << "' with '"
338                << comp.s2 << "'";
339    }
340}
341
342TEST(String, Reserve0OnEmptyString) {
343    String s;
344    // This is really to check that this doesn't crash.
345    ::memset(&s, 0, sizeof(s));
346    s.reserve(0U);
347}
348
349TEST(String, Swap) {
350    const String kShortString1("Hello World!");
351    const String kLongString1("A very long string that will likely "
352            "exceed the small string optimization storage buffer");
353    const String kShortString2("Menthe a l'eau");
354    const String kLongString2("Harold Ramis, Chicago actor, writer "
355            "and director, dead at 69");
356
357    // Swap two short strings.
358    {
359        String sa = kShortString1;
360        String sb = kShortString2;
361        sa.swap(&sb);
362        EXPECT_EQ(kShortString2, sa);
363        EXPECT_EQ(kShortString1, sb);
364    }
365
366    // Swap one short + one long string.
367    {
368        String sa = kShortString1;
369        String sb = kLongString1;
370        sa.swap(&sb);
371        EXPECT_EQ(kLongString1, sa);
372        EXPECT_EQ(kShortString1, sb);
373    }
374
375    // Swap one long + one short string.
376    {
377        String sa = kLongString1;
378        String sb = kLongString2;
379        sa.swap(&sb);
380        EXPECT_EQ(kLongString2, sa);
381        EXPECT_EQ(kLongString1, sb);
382    }
383}
384
385}  // namespace base
386}  // namespace android
387