• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,EmptyString_Returns0)48 TEST(ClampedCString, EmptyString_Returns0) {
49   EXPECT_TRUE(ClampedCString("", 0).empty());
50   EXPECT_TRUE(ClampedCString("", 100).empty());
51 }
52 
TEST(ClampedCString,MaxLongerThanString_ReturnsStr)53 TEST(ClampedCString, MaxLongerThanString_ReturnsStr) {
54   static constexpr char kInput[] = "12345";
55   const std::string_view result = ClampedCString(kInput, 100);
56   EXPECT_EQ(result.size(), strlen(kInput));
57   EXPECT_EQ(result.data(), &kInput[0]);
58 }
59 
TEST(ClampedCString,StringMaxLongerThanMax_ClampsView)60 TEST(ClampedCString, StringMaxLongerThanMax_ClampsView) {
61   static constexpr char kInput[] = "12345";
62 
63   EXPECT_TRUE(ClampedCString(kInput, 0).empty());
64 
65   const std::string_view result = ClampedCString(kInput, 4);
66   EXPECT_EQ(result.size(), 4u);
67   EXPECT_EQ(result.data(), &kInput[0]);
68 }
69 
TEST(ClampedCString,FullStringView)70 TEST(ClampedCString, FullStringView) {
71   static constexpr char kInput[] = "12345";
72   const std::string_view result = ClampedCString(kInput);
73   EXPECT_EQ(result.size(), strlen(kInput));
74   EXPECT_EQ(result.data(), &kInput[0]);
75 }
76 
TEST(NullTerminatedLength,EmptyString_RequiresNullTerminator)77 TEST(NullTerminatedLength, EmptyString_RequiresNullTerminator) {
78   EXPECT_TRUE(NullTerminatedLength("", 0).status().IsOutOfRange());
79 
80   ASSERT_TRUE(NullTerminatedLength("", 100).status().ok());
81   EXPECT_EQ(0u, NullTerminatedLength("", 100).value());
82 }
83 
TEST(NullTerminatedLength,MaxLongerThanString_ReturnsStrlen)84 TEST(NullTerminatedLength, MaxLongerThanString_ReturnsStrlen) {
85   ASSERT_TRUE(NullTerminatedLength("12345", 100).status().ok());
86   EXPECT_EQ(5u, NullTerminatedLength("12345", 100).value());
87 }
88 
TEST(NullTerminatedLength,StringMaxLongerThanMax_Fails)89 TEST(NullTerminatedLength, StringMaxLongerThanMax_Fails) {
90   EXPECT_TRUE(NullTerminatedLength("12345", 0).status().IsOutOfRange());
91   EXPECT_TRUE(NullTerminatedLength("12345", 4).status().IsOutOfRange());
92 }
93 
TEST(NullTerminatedLength,LengthEqualsMax)94 TEST(NullTerminatedLength, LengthEqualsMax) {
95   static constexpr char kInput[] = "12345";
96   ASSERT_TRUE(NullTerminatedLength(kInput).ok());
97   EXPECT_EQ(5u, NullTerminatedLength(kInput).value());
98 }
99 
100 class TestWithBuffer : public ::testing::Test {
101  protected:
102   static constexpr char kStartingString[] = "!@#$%^&*()!@#$%^&*()";
103 
TestWithBuffer()104   TestWithBuffer() { std::memcpy(buffer_, kStartingString, sizeof(buffer_)); }
105 
106   char buffer_[sizeof(kStartingString)];
107 };
108 
109 class CopyTest : public TestWithBuffer {};
110 
TEST_F(CopyTest,EmptyStringView_WritesNullTerminator)111 TEST_F(CopyTest, EmptyStringView_WritesNullTerminator) {
112   EXPECT_EQ(0u, Copy("", buffer_).size());
113   EXPECT_EQ('\0', buffer_[0]);
114 }
115 
TEST_F(CopyTest,EmptyBuffer_WritesNothing)116 TEST_F(CopyTest, EmptyBuffer_WritesNothing) {
117   auto result = Copy("Hello", span(buffer_, 0));
118   EXPECT_EQ(0u, result.size());
119   EXPECT_FALSE(result.ok());
120   EXPECT_STREQ(kStartingString, buffer_);
121 }
122 
TEST_F(CopyTest,TooSmall_Truncates)123 TEST_F(CopyTest, TooSmall_Truncates) {
124   auto result = Copy("Hi!", span(buffer_, 3));
125   EXPECT_EQ(2u, result.size());
126   EXPECT_FALSE(result.ok());
127   EXPECT_STREQ("Hi", buffer_);
128 }
129 
TEST_F(CopyTest,ExactFit)130 TEST_F(CopyTest, ExactFit) {
131   auto result = Copy("Hi!", span(buffer_, 4));
132   EXPECT_EQ(3u, result.size());
133   EXPECT_TRUE(result.ok());
134   EXPECT_STREQ("Hi!", buffer_);
135 }
136 
TEST_F(CopyTest,NullTerminatorsInString)137 TEST_F(CopyTest, NullTerminatorsInString) {
138   ASSERT_EQ(4u, Copy("\0!\0\0"sv, span(buffer_, 5)).size());
139   EXPECT_EQ("\0!\0\0"sv, std::string_view(buffer_, 4));
140 }
141 
142 class InlineStringUtilTest : public ::testing::Test {
143  protected:
144   InlineString<5> string_;
145 };
146 
TEST_F(InlineStringUtilTest,Assign_EmptyStringView_WritesNullTerminator)147 TEST_F(InlineStringUtilTest, Assign_EmptyStringView_WritesNullTerminator) {
148   EXPECT_EQ(OkStatus(), Assign(string_, ""));
149   EXPECT_EQ(string_, "");
150 }
151 
TEST_F(InlineStringUtilTest,Assign_EmptyBuffer_WritesNothing)152 TEST_F(InlineStringUtilTest, Assign_EmptyBuffer_WritesNothing) {
153   InlineString<0> zero_capacity;
154   EXPECT_EQ(Status::ResourceExhausted(), Assign(zero_capacity, "Hello"));
155   EXPECT_TRUE(zero_capacity.empty());
156   EXPECT_EQ(zero_capacity.c_str()[0], '\0');
157 }
158 
TEST_F(InlineStringUtilTest,Assign_TooSmall_Truncates)159 TEST_F(InlineStringUtilTest, Assign_TooSmall_Truncates) {
160   EXPECT_EQ(Status::ResourceExhausted(), Assign(string_, "12345HELLO?"));
161   EXPECT_EQ("12345", string_);
162 }
163 
TEST_F(InlineStringUtilTest,Assign_ExactFit)164 TEST_F(InlineStringUtilTest, Assign_ExactFit) {
165   EXPECT_EQ(OkStatus(), Assign(string_, "12345"));
166   EXPECT_EQ("12345", string_);
167 }
168 
TEST_F(InlineStringUtilTest,Assign_NullTerminatorsInString)169 TEST_F(InlineStringUtilTest, Assign_NullTerminatorsInString) {
170   EXPECT_EQ(OkStatus(), Assign(string_, "\0!\0\0\0"sv));
171   EXPECT_EQ("\0!\0\0\0"sv, string_);
172 }
173 
TEST_F(InlineStringUtilTest,Assign_ExistingContent_Replaces)174 TEST_F(InlineStringUtilTest, Assign_ExistingContent_Replaces) {
175   string_ = "12345";
176   EXPECT_EQ(OkStatus(), Assign(string_, ""));
177   EXPECT_EQ("", string_);
178 }
179 
TEST_F(InlineStringUtilTest,Assign_ExistingContent_ExactFit)180 TEST_F(InlineStringUtilTest, Assign_ExistingContent_ExactFit) {
181   string_.append("yo");
182   EXPECT_EQ(OkStatus(), Assign(string_, "12345"));
183   EXPECT_EQ("12345", string_);
184 }
185 
TEST_F(InlineStringUtilTest,Assign_ExistingContent_Truncates)186 TEST_F(InlineStringUtilTest, Assign_ExistingContent_Truncates) {
187   string_.append("yo");
188   EXPECT_EQ(Status::ResourceExhausted(), Assign(string_, "1234567"));
189   EXPECT_EQ("12345", string_);
190 }
191 
TEST_F(InlineStringUtilTest,Append_EmptyStringView_WritesNullTerminator)192 TEST_F(InlineStringUtilTest, Append_EmptyStringView_WritesNullTerminator) {
193   EXPECT_EQ(OkStatus(), Append(string_, ""));
194   EXPECT_EQ(string_, "");
195 }
196 
TEST_F(InlineStringUtilTest,Append_EmptyBuffer_WritesNothing)197 TEST_F(InlineStringUtilTest, Append_EmptyBuffer_WritesNothing) {
198   InlineString<0> zero_capacity;
199   EXPECT_EQ(Status::ResourceExhausted(), Append(zero_capacity, "Hello"));
200   EXPECT_TRUE(zero_capacity.empty());
201   EXPECT_EQ(zero_capacity.c_str()[0], '\0');
202 }
203 
TEST_F(InlineStringUtilTest,Append_TooSmall_Truncates)204 TEST_F(InlineStringUtilTest, Append_TooSmall_Truncates) {
205   EXPECT_EQ(Status::ResourceExhausted(), Append(string_, "12345HELLO?"));
206   EXPECT_EQ("12345", string_);
207 }
208 
TEST_F(InlineStringUtilTest,Append_ExactFit)209 TEST_F(InlineStringUtilTest, Append_ExactFit) {
210   EXPECT_EQ(OkStatus(), Append(string_, "12345"));
211   EXPECT_EQ("12345", string_);
212 }
213 
TEST_F(InlineStringUtilTest,Append_NullTerminatorsInString)214 TEST_F(InlineStringUtilTest, Append_NullTerminatorsInString) {
215   EXPECT_EQ(OkStatus(), Append(string_, "\0!\0\0\0"sv));
216   EXPECT_EQ("\0!\0\0\0"sv, string_);
217 }
218 
TEST_F(InlineStringUtilTest,Append_ExistingContent_AppendNothing)219 TEST_F(InlineStringUtilTest, Append_ExistingContent_AppendNothing) {
220   string_ = "12345";
221   EXPECT_EQ(OkStatus(), Append(string_, ""));
222   EXPECT_EQ("12345", string_);
223 }
224 
TEST_F(InlineStringUtilTest,Append_ExistingContent_ExactFit)225 TEST_F(InlineStringUtilTest, Append_ExistingContent_ExactFit) {
226   string_.append("yo");
227   EXPECT_EQ(OkStatus(), Append(string_, "123"));
228   EXPECT_EQ("yo123", string_);
229 }
230 
TEST_F(InlineStringUtilTest,Append_ExistingContent_Truncates)231 TEST_F(InlineStringUtilTest, Append_ExistingContent_Truncates) {
232   string_.append("yo");
233   EXPECT_EQ(Status::ResourceExhausted(), Append(string_, "12345"));
234   EXPECT_EQ("yo123", string_);
235 }
236 
237 class PrintableCopyTest : public TestWithBuffer {};
238 
TEST_F(PrintableCopyTest,EmptyBuffer_WritesNothing)239 TEST_F(PrintableCopyTest, EmptyBuffer_WritesNothing) {
240   auto result = PrintableCopy("Hello", span(buffer_, 0));
241   EXPECT_EQ(0u, result.size());
242   EXPECT_FALSE(result.ok());
243   EXPECT_STREQ(kStartingString, buffer_);
244 }
245 
TEST_F(PrintableCopyTest,TooSmall_Truncates)246 TEST_F(PrintableCopyTest, TooSmall_Truncates) {
247   auto result = PrintableCopy("Hi!", span(buffer_, 3));
248   EXPECT_EQ(2u, result.size());
249   EXPECT_FALSE(result.ok());
250   EXPECT_STREQ("Hi", buffer_);
251 }
252 
TEST_F(PrintableCopyTest,ExactFit)253 TEST_F(PrintableCopyTest, ExactFit) {
254   auto result = PrintableCopy("Hi!", span(buffer_, 4));
255   EXPECT_EQ(3u, result.size());
256   EXPECT_TRUE(result.ok());
257   EXPECT_STREQ("Hi!", buffer_);
258 }
259 
TEST_F(PrintableCopyTest,StartingString)260 TEST_F(PrintableCopyTest, StartingString) {
261   memset(buffer_, '\0', sizeof(buffer_));
262   auto result = PrintableCopy(kStartingString, span(buffer_));
263   EXPECT_EQ(sizeof(kStartingString) - 1, result.size());
264   EXPECT_TRUE(result.ok());
265   EXPECT_STREQ(kStartingString, buffer_);
266 }
267 
TEST_F(PrintableCopyTest,NullTerminatorsInString)268 TEST_F(PrintableCopyTest, NullTerminatorsInString) {
269   ASSERT_EQ(4u, PrintableCopy("\0!\0\0"sv, span(buffer_, 5)).size());
270   EXPECT_STREQ(".!..", buffer_);
271 }
272 
TEST_F(PrintableCopyTest,ControlCharsInString)273 TEST_F(PrintableCopyTest, ControlCharsInString) {
274   ASSERT_EQ(
275       14u,
276       PrintableCopy("\n!\t\n\x10\x7F\xFF\vabcd\b\r"sv, span(buffer_)).size());
277   EXPECT_STREQ(".!......abcd..", buffer_);
278 }
279 
280 }  // namespace
281 }  // namespace pw::string
282