xref: /llvm-project/libc/test/src/__support/CPP/string_test.cpp (revision b6bc9d72f65a5086f310f321e969d96e9a559e75)
1 //===-- Unittests for string ----------------------------------------------===//
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 "src/__support/CPP/string.h"
10 #include "test/UnitTest/Test.h"
11 
12 using LIBC_NAMESPACE::cpp::string;
13 using LIBC_NAMESPACE::cpp::string_view;
14 using LIBC_NAMESPACE::cpp::to_string;
15 
TEST(LlvmLibcStringTest,InitializeEmpty)16 TEST(LlvmLibcStringTest, InitializeEmpty) {
17   const string s;
18   ASSERT_EQ(s.size(), size_t(0));
19   ASSERT_TRUE(s.empty());
20   ASSERT_STREQ(s.data(), "");
21   ASSERT_STREQ(s.c_str(), "");
22   ASSERT_EQ(s.data(), s.c_str());
23   ASSERT_EQ(s.capacity(), size_t(0));
24 }
25 
TEST(LlvmLibcStringTest,InitializeCString)26 TEST(LlvmLibcStringTest, InitializeCString) {
27   const char *const str = "abc";
28   const string s(str);
29   ASSERT_EQ(s.size(), size_t(3));
30   ASSERT_FALSE(s.empty());
31   ASSERT_NE(s.data(), &str[0]);
32   ASSERT_EQ(s[0], 'a');
33   ASSERT_EQ(s[1], 'b');
34   ASSERT_EQ(s[2], 'c');
35   ASSERT_EQ(s.front(), 'a');
36   ASSERT_EQ(s.back(), 'c');
37   ASSERT_EQ(s.data(), s.c_str());
38 }
39 
TEST(LlvmLibcStringTest,ToCString)40 TEST(LlvmLibcStringTest, ToCString) {
41   const char *const str = "abc";
42   string s(str);
43   const char *cstr = s.c_str();
44   ASSERT_EQ(s.size(), size_t(3));
45   ASSERT_STREQ(str, cstr);
46 }
47 
TEST(LlvmLibcStringTest,ToStringView)48 TEST(LlvmLibcStringTest, ToStringView) {
49   const char *const str = "abc";
50   string s(str);
51   string_view view = s;
52   ASSERT_EQ(view, string_view(str));
53 }
54 
TEST(LlvmLibcStringTest,InitializeCStringWithSize)55 TEST(LlvmLibcStringTest, InitializeCStringWithSize) {
56   const char *const str = "abc";
57   const string s(str, 2);
58   ASSERT_EQ(s.size(), size_t(2));
59   ASSERT_EQ(s[0], 'a');
60   ASSERT_EQ(s[1], 'b');
61   ASSERT_EQ(s.front(), 'a');
62   ASSERT_EQ(s.back(), 'b');
63 }
64 
TEST(LlvmLibcStringTest,InitializeStringView)65 TEST(LlvmLibcStringTest, InitializeStringView) {
66   const string_view str = "ab";
67   const string s(str);
68   ASSERT_EQ(s.size(), size_t(2));
69   ASSERT_EQ(s[0], 'a');
70   ASSERT_EQ(s[1], 'b');
71   ASSERT_EQ(s.front(), 'a');
72   ASSERT_EQ(s.back(), 'b');
73 }
74 
TEST(LlvmLibcStringTest,InitializeRepeatedChar)75 TEST(LlvmLibcStringTest, InitializeRepeatedChar) {
76   const string s(4, '1');
77   ASSERT_EQ(string_view(s), string_view("1111"));
78 }
79 
TEST(LlvmLibcStringTest,InitializeZeorChar)80 TEST(LlvmLibcStringTest, InitializeZeorChar) {
81   const string s(0, '1');
82   ASSERT_TRUE(s.empty());
83 }
84 
TEST(LlvmLibcStringTest,CopyConstruct)85 TEST(LlvmLibcStringTest, CopyConstruct) {
86   const char *const str = "abc";
87   string a(str);
88   string b(a);
89   // Same content
90   ASSERT_STREQ(a.c_str(), str);
91   ASSERT_STREQ(b.c_str(), str);
92   // Different pointers
93   ASSERT_NE(a.data(), b.data());
94 }
95 
move(string & value)96 string &&move(string &value) { return static_cast<string &&>(value); }
97 
TEST(LlvmLibcStringTest,CopyAssign)98 TEST(LlvmLibcStringTest, CopyAssign) {
99   const char *const str = "abc";
100   string a(str);
101   string b;
102   b = a;
103   // Same content
104   ASSERT_STREQ(a.c_str(), str);
105   ASSERT_STREQ(b.c_str(), str);
106   // Different pointers
107   ASSERT_NE(a.data(), b.data());
108 }
109 
TEST(LlvmLibcStringTest,MoveConstruct)110 TEST(LlvmLibcStringTest, MoveConstruct) {
111   const char *const str = "abc";
112   string a(str);
113   string b(move(a));
114   ASSERT_STREQ(b.c_str(), str);
115   ASSERT_STREQ(a.c_str(), "");
116 }
117 
TEST(LlvmLibcStringTest,MoveAssign)118 TEST(LlvmLibcStringTest, MoveAssign) {
119   const char *const str = "abc";
120   string a(str);
121   string b;
122   b = move(a);
123   ASSERT_STREQ(b.c_str(), str);
124   ASSERT_STREQ(a.c_str(), "");
125 }
126 
TEST(LlvmLibcStringTest,StringViewAssign)127 TEST(LlvmLibcStringTest, StringViewAssign) {
128   const string_view str = "ab";
129   string s;
130   s = str;
131   ASSERT_EQ(s.size(), size_t(2));
132   ASSERT_EQ(s[0], 'a');
133   ASSERT_EQ(s[1], 'b');
134   ASSERT_EQ(s.front(), 'a');
135   ASSERT_EQ(s.back(), 'b');
136 }
137 
TEST(LlvmLibcStringTest,Concat)138 TEST(LlvmLibcStringTest, Concat) {
139   const char *const str = "abc";
140   string a(str);
141   string b;
142   b += a;
143   ASSERT_STREQ(b.c_str(), "abc");
144   b += a;
145   ASSERT_STREQ(b.c_str(), "abcabc");
146 }
147 
TEST(LlvmLibcStringTest,AddChar)148 TEST(LlvmLibcStringTest, AddChar) {
149   string a;
150   a += 'a';
151   ASSERT_STREQ(a.c_str(), "a");
152   a += 'b';
153   ASSERT_STREQ(a.c_str(), "ab");
154 }
155 
TEST(LlvmLibcStringTest,ResizeCapacityAndNullTermination)156 TEST(LlvmLibcStringTest, ResizeCapacityAndNullTermination) {
157   string a;
158   // Empty
159   ASSERT_EQ(a.capacity(), size_t(0));
160   ASSERT_EQ(a.data()[0], '\0');
161   // Still empty
162   a.resize(0);
163   ASSERT_EQ(a.capacity(), size_t(0));
164   ASSERT_EQ(a.data()[0], '\0');
165   // One char
166   a.resize(1);
167   ASSERT_EQ(a.size(), size_t(1));
168   ASSERT_GE(a.capacity(), size_t(2));
169   ASSERT_EQ(a.data()[1], '\0');
170   // Clear
171   a.resize(0);
172   ASSERT_EQ(a.size(), size_t(0));
173   ASSERT_GE(a.capacity(), size_t(2));
174   ASSERT_EQ(a.data()[0], '\0');
175   // Resize and check zero initialized
176   a.resize(10);
177   ASSERT_EQ(a.size(), size_t(10));
178   ASSERT_GE(a.capacity(), size_t(10));
179   for (size_t i = 0; i < 10; ++i)
180     ASSERT_EQ(a[i], '\0');
181 }
182 
TEST(LlvmLibcStringTest,ConcatWithCString)183 TEST(LlvmLibcStringTest, ConcatWithCString) {
184   ASSERT_STREQ((string("a") + string("b")).c_str(), "ab");
185   ASSERT_STREQ((string("a") + "b").c_str(), "ab");
186   ASSERT_STREQ(("a" + string("b")).c_str(), "ab");
187 }
188 
TEST(LlvmLibcStringTest,Comparison)189 TEST(LlvmLibcStringTest, Comparison) {
190   // Here we simply check that comparison of string and string_view have the
191   // same semantic.
192   struct CStringPair {
193     const char *const a;
194     const char *const b;
195   } kTestPairs[] = {{"a", "b"}, {"", "xyz"}};
196   for (const auto [pa, pb] : kTestPairs) {
197     const string sa(pa);
198     const string sb(pb);
199     const string_view sva(pa);
200     const string_view svb(pb);
201     ASSERT_EQ(sa == sb, sva == svb);
202     ASSERT_EQ(sa != sb, sva != svb);
203     ASSERT_EQ(sa >= sb, sva >= svb);
204     ASSERT_EQ(sa <= sb, sva <= svb);
205     ASSERT_EQ(sa < sb, sva < svb);
206     ASSERT_EQ(sa > sb, sva > svb);
207   }
208 }
209 
TEST(LlvmLibcStringTest,ToString)210 TEST(LlvmLibcStringTest, ToString) {
211   struct CStringPair {
212     const int value;
213     const string str;
214   } kTestPairs[] = {{123, "123"}, {0, "0"}, {-321, "-321"}};
215   for (const auto &[value, str] : kTestPairs) {
216     ASSERT_EQ(to_string((int)(value)), str);
217     ASSERT_EQ(to_string((long)(value)), str);
218     ASSERT_EQ(to_string((long long)(value)), str);
219     if (value >= 0) {
220       ASSERT_EQ(to_string((unsigned int)(value)), str);
221       ASSERT_EQ(to_string((unsigned long)(value)), str);
222       ASSERT_EQ(to_string((unsigned long long)(value)), str);
223     }
224   }
225 }
226