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
12using LIBC_NAMESPACE::cpp::string;
13using LIBC_NAMESPACE::cpp::string_view;
14using LIBC_NAMESPACE::cpp::to_string;
15
16TEST(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
26TEST(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
40TEST(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
48TEST(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
55TEST(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
65TEST(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
75TEST(LlvmLibcStringTest, InitializeRepeatedChar) {
76 const string s(4, '1');
77 ASSERT_EQ(string_view(s), string_view("1111"));
78}
79
80TEST(LlvmLibcStringTest, InitializeZeorChar) {
81 const string s(0, '1');
82 ASSERT_TRUE(s.empty());
83}
84
85TEST(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
96string &&move(string &value) { return static_cast<string &&>(value); }
97
98TEST(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
110TEST(LlvmLibcStringTest, MoveConstruct) {
111 const char *const str = "abc";
112 string a(str);
113 string b(move(value&: a));
114 ASSERT_STREQ(b.c_str(), str);
115 ASSERT_STREQ(a.c_str(), "");
116}
117
118TEST(LlvmLibcStringTest, MoveAssign) {
119 const char *const str = "abc";
120 string a(str);
121 string b;
122 b = move(value&: a);
123 ASSERT_STREQ(b.c_str(), str);
124 ASSERT_STREQ(a.c_str(), "");
125}
126
127TEST(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
138TEST(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
148TEST(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
156TEST(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(size: 0);
163 ASSERT_EQ(a.capacity(), size_t(0));
164 ASSERT_EQ(a.data()[0], '\0');
165 // One char
166 a.resize(size: 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(size: 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(size: 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
183TEST(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
189TEST(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: "a", .b: "b"}, {.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
210TEST(LlvmLibcStringTest, ToString) {
211 struct CStringPair {
212 const int value;
213 const string str;
214 } kTestPairs[] = {{.value: 123, .str: "123"}, {.value: 0, .str: "0"}, {.value: -321, .str: "-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

source code of libc/test/src/__support/CPP/string_test.cpp