xref: /aosp_15_r20/external/pigweed/pw_string/util_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_string/util.h"
16 
17 #include <cstring>
18 
19 #include "pw_unit_test/framework.h"
20 
21 namespace pw::string {
22 namespace {
23 
24 using namespace std::literals::string_view_literals;
25 
TEST(ClampedLength,Nullptr_Returns0)26 TEST(ClampedLength, Nullptr_Returns0) {
27   EXPECT_EQ(0u, internal::ClampedLength(nullptr, 100));
28 }
29 
TEST(ClampedLength,EmptyString_Returns0)30 TEST(ClampedLength, EmptyString_Returns0) {
31   EXPECT_EQ(0u, internal::ClampedLength("", 0));
32   EXPECT_EQ(0u, internal::ClampedLength("", 100));
33 }
34 
TEST(ClampedLength,MaxLongerThanString_ReturnsStrlen)35 TEST(ClampedLength, MaxLongerThanString_ReturnsStrlen) {
36   EXPECT_EQ(5u, internal::ClampedLength("12345", 100));
37 }
38 
TEST(ClampedLength,StringMaxLongerThanMax_ReturnsMax)39 TEST(ClampedLength, StringMaxLongerThanMax_ReturnsMax) {
40   EXPECT_EQ(0u, internal::ClampedLength("12345", 0));
41   EXPECT_EQ(4u, internal::ClampedLength("12345", 4));
42 }
43 
TEST(ClampedLength,LengthEqualsMax)44 TEST(ClampedLength, LengthEqualsMax) {
45   EXPECT_EQ(5u, internal::ClampedLength("12345", 5));
46 }
47 
TEST(ClampedCString,NullPtr_ReturnsEmpty)48 TEST(ClampedCString, NullPtr_ReturnsEmpty) {
49   EXPECT_TRUE(ClampedCString(nullptr, 100).empty());
50 }
51 
TEST(ClampedCString,EmptyString_Returns0)52 TEST(ClampedCString, EmptyString_Returns0) {
53   EXPECT_TRUE(ClampedCString("", 0).empty());
54   EXPECT_TRUE(ClampedCString("", 100).empty());
55 }
56 
TEST(ClampedCString,MaxLongerThanString_ReturnsStr)57 TEST(ClampedCString, MaxLongerThanString_ReturnsStr) {
58   static constexpr char kInput[] = "12345";
59   const std::string_view result = ClampedCString(kInput, 100);
60   EXPECT_EQ(result.size(), strlen(kInput));
61   EXPECT_EQ(result.data(), &kInput[0]);
62 }
63 
TEST(ClampedCString,StringMaxLongerThanMax_ClampsView)64 TEST(ClampedCString, StringMaxLongerThanMax_ClampsView) {
65   static constexpr char kInput[] = "12345";
66 
67   EXPECT_TRUE(ClampedCString(kInput, 0).empty());
68 
69   const std::string_view result = ClampedCString(kInput, 4);
70   EXPECT_EQ(result.size(), 4u);
71   EXPECT_EQ(result.data(), &kInput[0]);
72 }
73 
TEST(ClampedCString,FullStringView)74 TEST(ClampedCString, FullStringView) {
75   static constexpr char kInput[] = "12345";
76   const std::string_view result = ClampedCString(kInput);
77   EXPECT_EQ(result.size(), strlen(kInput));
78   EXPECT_EQ(result.data(), &kInput[0]);
79 }
80 
TEST(NullTerminatedLength,EmptyString_RequiresNullTerminator)81 TEST(NullTerminatedLength, EmptyString_RequiresNullTerminator) {
82   EXPECT_TRUE(NullTerminatedLength("", 0).status().IsOutOfRange());
83 
84   ASSERT_TRUE(NullTerminatedLength("", 100).status().ok());
85   EXPECT_EQ(0u, NullTerminatedLength("", 100).value());
86 }
87 
TEST(NullTerminatedLength,MaxLongerThanString_ReturnsStrlen)88 TEST(NullTerminatedLength, MaxLongerThanString_ReturnsStrlen) {
89   ASSERT_TRUE(NullTerminatedLength("12345", 100).status().ok());
90   EXPECT_EQ(5u, NullTerminatedLength("12345", 100).value());
91 }
92 
TEST(NullTerminatedLength,StringMaxLongerThanMax_Fails)93 TEST(NullTerminatedLength, StringMaxLongerThanMax_Fails) {
94   EXPECT_TRUE(NullTerminatedLength("12345", 0).status().IsOutOfRange());
95   EXPECT_TRUE(NullTerminatedLength("12345", 4).status().IsOutOfRange());
96 }
97 
TEST(NullTerminatedLength,LengthEqualsMax)98 TEST(NullTerminatedLength, LengthEqualsMax) {
99   static constexpr char kInput[] = "12345";
100   ASSERT_TRUE(NullTerminatedLength(kInput).ok());
101   EXPECT_EQ(5u, NullTerminatedLength(kInput).value());
102 }
103 
104 class TestWithBuffer : public ::testing::Test {
105  protected:
106   static constexpr char kStartingString[] = "!@#$%^&*()!@#$%^&*()";
107 
TestWithBuffer()108   TestWithBuffer() { std::memcpy(buffer_, kStartingString, sizeof(buffer_)); }
109 
110   char buffer_[sizeof(kStartingString)];
111 };
112 
113 class CopyTest : public TestWithBuffer {};
114 
TEST_F(CopyTest,EmptyStringView_WritesNullTerminator)115 TEST_F(CopyTest, EmptyStringView_WritesNullTerminator) {
116   EXPECT_EQ(0u, Copy("", buffer_).size());
117   EXPECT_EQ('\0', buffer_[0]);
118 }
119 
TEST_F(CopyTest,EmptyBuffer_WritesNothing)120 TEST_F(CopyTest, EmptyBuffer_WritesNothing) {
121   auto result = Copy("Hello", span(buffer_, 0));
122   EXPECT_EQ(0u, result.size());
123   EXPECT_FALSE(result.ok());
124   EXPECT_STREQ(kStartingString, buffer_);
125 }
126 
TEST_F(CopyTest,TooSmall_Truncates)127 TEST_F(CopyTest, TooSmall_Truncates) {
128   auto result = Copy("Hi!", span(buffer_, 3));
129   EXPECT_EQ(2u, result.size());
130   EXPECT_FALSE(result.ok());
131   EXPECT_STREQ("Hi", buffer_);
132 }
133 
TEST_F(CopyTest,ExactFit)134 TEST_F(CopyTest, ExactFit) {
135   auto result = Copy("Hi!", span(buffer_, 4));
136   EXPECT_EQ(3u, result.size());
137   EXPECT_TRUE(result.ok());
138   EXPECT_STREQ("Hi!", buffer_);
139 }
140 
TEST_F(CopyTest,NullTerminatorsInString)141 TEST_F(CopyTest, NullTerminatorsInString) {
142   ASSERT_EQ(4u, Copy("\0!\0\0"sv, span(buffer_, 5)).size());
143   EXPECT_EQ("\0!\0\0"sv, std::string_view(buffer_, 4));
144 }
145 
146 class InlineStringUtilTest : public ::testing::Test {
147  protected:
148   InlineString<5> string_;
149 };
150 
TEST_F(InlineStringUtilTest,Assign_EmptyStringView_WritesNullTerminator)151 TEST_F(InlineStringUtilTest, Assign_EmptyStringView_WritesNullTerminator) {
152   EXPECT_EQ(OkStatus(), Assign(string_, ""));
153   EXPECT_EQ(string_, "");
154 }
155 
TEST_F(InlineStringUtilTest,Assign_EmptyBuffer_WritesNothing)156 TEST_F(InlineStringUtilTest, Assign_EmptyBuffer_WritesNothing) {
157   InlineString<0> zero_capacity;
158   EXPECT_EQ(Status::ResourceExhausted(), Assign(zero_capacity, "Hello"));
159   EXPECT_TRUE(zero_capacity.empty());
160   EXPECT_EQ(zero_capacity.c_str()[0], '\0');
161 }
162 
TEST_F(InlineStringUtilTest,Assign_TooSmall_Truncates)163 TEST_F(InlineStringUtilTest, Assign_TooSmall_Truncates) {
164   EXPECT_EQ(Status::ResourceExhausted(), Assign(string_, "12345HELLO?"));
165   EXPECT_EQ("12345", string_);
166 }
167 
TEST_F(InlineStringUtilTest,Assign_ExactFit)168 TEST_F(InlineStringUtilTest, Assign_ExactFit) {
169   EXPECT_EQ(OkStatus(), Assign(string_, "12345"));
170   EXPECT_EQ("12345", string_);
171 }
172 
TEST_F(InlineStringUtilTest,Assign_NullTerminatorsInString)173 TEST_F(InlineStringUtilTest, Assign_NullTerminatorsInString) {
174   EXPECT_EQ(OkStatus(), Assign(string_, "\0!\0\0\0"sv));
175   EXPECT_EQ("\0!\0\0\0"sv, string_);
176 }
177 
TEST_F(InlineStringUtilTest,Assign_ExistingContent_Replaces)178 TEST_F(InlineStringUtilTest, Assign_ExistingContent_Replaces) {
179   string_ = "12345";
180   EXPECT_EQ(OkStatus(), Assign(string_, ""));
181   EXPECT_EQ("", string_);
182 }
183 
TEST_F(InlineStringUtilTest,Assign_ExistingContent_ExactFit)184 TEST_F(InlineStringUtilTest, Assign_ExistingContent_ExactFit) {
185   string_.append("yo");
186   EXPECT_EQ(OkStatus(), Assign(string_, "12345"));
187   EXPECT_EQ("12345", string_);
188 }
189 
TEST_F(InlineStringUtilTest,Assign_ExistingContent_Truncates)190 TEST_F(InlineStringUtilTest, Assign_ExistingContent_Truncates) {
191   string_.append("yo");
192   EXPECT_EQ(Status::ResourceExhausted(), Assign(string_, "1234567"));
193   EXPECT_EQ("12345", string_);
194 }
195 
TEST_F(InlineStringUtilTest,Append_EmptyStringView_WritesNullTerminator)196 TEST_F(InlineStringUtilTest, Append_EmptyStringView_WritesNullTerminator) {
197   EXPECT_EQ(OkStatus(), Append(string_, ""));
198   EXPECT_EQ(string_, "");
199 }
200 
TEST_F(InlineStringUtilTest,Append_EmptyBuffer_WritesNothing)201 TEST_F(InlineStringUtilTest, Append_EmptyBuffer_WritesNothing) {
202   InlineString<0> zero_capacity;
203   EXPECT_EQ(Status::ResourceExhausted(), Append(zero_capacity, "Hello"));
204   EXPECT_TRUE(zero_capacity.empty());
205   EXPECT_EQ(zero_capacity.c_str()[0], '\0');
206 }
207 
TEST_F(InlineStringUtilTest,Append_TooSmall_Truncates)208 TEST_F(InlineStringUtilTest, Append_TooSmall_Truncates) {
209   EXPECT_EQ(Status::ResourceExhausted(), Append(string_, "12345HELLO?"));
210   EXPECT_EQ("12345", string_);
211 }
212 
TEST_F(InlineStringUtilTest,Append_ExactFit)213 TEST_F(InlineStringUtilTest, Append_ExactFit) {
214   EXPECT_EQ(OkStatus(), Append(string_, "12345"));
215   EXPECT_EQ("12345", string_);
216 }
217 
TEST_F(InlineStringUtilTest,Append_NullTerminatorsInString)218 TEST_F(InlineStringUtilTest, Append_NullTerminatorsInString) {
219   EXPECT_EQ(OkStatus(), Append(string_, "\0!\0\0\0"sv));
220   EXPECT_EQ("\0!\0\0\0"sv, string_);
221 }
222 
TEST_F(InlineStringUtilTest,Append_ExistingContent_AppendNothing)223 TEST_F(InlineStringUtilTest, Append_ExistingContent_AppendNothing) {
224   string_ = "12345";
225   EXPECT_EQ(OkStatus(), Append(string_, ""));
226   EXPECT_EQ("12345", string_);
227 }
228 
TEST_F(InlineStringUtilTest,Append_ExistingContent_ExactFit)229 TEST_F(InlineStringUtilTest, Append_ExistingContent_ExactFit) {
230   string_.append("yo");
231   EXPECT_EQ(OkStatus(), Append(string_, "123"));
232   EXPECT_EQ("yo123", string_);
233 }
234 
TEST_F(InlineStringUtilTest,Append_ExistingContent_Truncates)235 TEST_F(InlineStringUtilTest, Append_ExistingContent_Truncates) {
236   string_.append("yo");
237   EXPECT_EQ(Status::ResourceExhausted(), Append(string_, "12345"));
238   EXPECT_EQ("yo123", string_);
239 }
240 
241 class PrintableCopyTest : public TestWithBuffer {};
242 
TEST_F(PrintableCopyTest,EmptyBuffer_WritesNothing)243 TEST_F(PrintableCopyTest, EmptyBuffer_WritesNothing) {
244   auto result = PrintableCopy("Hello", span(buffer_, 0));
245   EXPECT_EQ(0u, result.size());
246   EXPECT_FALSE(result.ok());
247   EXPECT_STREQ(kStartingString, buffer_);
248 }
249 
TEST_F(PrintableCopyTest,TooSmall_Truncates)250 TEST_F(PrintableCopyTest, TooSmall_Truncates) {
251   auto result = PrintableCopy("Hi!", span(buffer_, 3));
252   EXPECT_EQ(2u, result.size());
253   EXPECT_FALSE(result.ok());
254   EXPECT_STREQ("Hi", buffer_);
255 }
256 
TEST_F(PrintableCopyTest,ExactFit)257 TEST_F(PrintableCopyTest, ExactFit) {
258   auto result = PrintableCopy("Hi!", span(buffer_, 4));
259   EXPECT_EQ(3u, result.size());
260   EXPECT_TRUE(result.ok());
261   EXPECT_STREQ("Hi!", buffer_);
262 }
263 
TEST_F(PrintableCopyTest,StartingString)264 TEST_F(PrintableCopyTest, StartingString) {
265   memset(buffer_, '\0', sizeof(buffer_));
266   auto result = PrintableCopy(kStartingString, span(buffer_));
267   EXPECT_EQ(sizeof(kStartingString) - 1, result.size());
268   EXPECT_TRUE(result.ok());
269   EXPECT_STREQ(kStartingString, buffer_);
270 }
271 
TEST_F(PrintableCopyTest,NullTerminatorsInString)272 TEST_F(PrintableCopyTest, NullTerminatorsInString) {
273   ASSERT_EQ(4u, PrintableCopy("\0!\0\0"sv, span(buffer_, 5)).size());
274   EXPECT_STREQ(".!..", buffer_);
275 }
276 
TEST_F(PrintableCopyTest,ControlCharsInString)277 TEST_F(PrintableCopyTest, ControlCharsInString) {
278   ASSERT_EQ(
279       14u,
280       PrintableCopy("\n!\t\n\x10\x7F\xFF\vabcd\b\r"sv, span(buffer_)).size());
281   EXPECT_STREQ(".!......abcd..", buffer_);
282 }
283 
284 }  // namespace
285 }  // namespace pw::string
286