blob: 1e0dc09395646d86a6c398be3b7da5b01e772f57 [file] [log] [blame]
Wyatt Heplerce9b9522019-11-11 10:45:48 -08001// Copyright 2019 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
Wyatt Hepler1a960942019-11-26 14:13:38 -08004// use this file except in compliance with the License. You may obtain a copy of
5// the License at
Wyatt Heplerce9b9522019-11-11 10:45:48 -08006//
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
Wyatt Hepler1a960942019-11-26 14:13:38 -080012// License for the specific language governing permissions and limitations under
13// the License.
Wyatt Heplerce9b9522019-11-11 10:45:48 -080014
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070015#include "pw_string/string_builder.h"
Wyatt Heplerce9b9522019-11-11 10:45:48 -080016
17#include <cinttypes>
18#include <cmath>
19#include <cstdint>
20#include <cstring>
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070021#include <span>
Wyatt Heplerce9b9522019-11-11 10:45:48 -080022#include <string_view>
23
24#include "gtest/gtest.h"
25#include "pw_string/format.h"
26
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070027namespace this_pw_test {
Wyatt Heplerce9b9522019-11-11 10:45:48 -080028
29struct CustomType {
30 uint32_t a;
31 uint32_t b;
32
33 static constexpr const char* kToString = "This is a CustomType";
34
35 CustomType() = default;
36
37 // Non-copyable to verify StringBuffer's << operator doesn't copy it.
38 CustomType(const CustomType&) = delete;
39 CustomType& operator=(const CustomType&) = delete;
40};
41
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070042} // namespace this_pw_test
Wyatt Heplerce9b9522019-11-11 10:45:48 -080043
44namespace pw {
45
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070046template <>
47StatusWithSize ToString<this_pw_test::CustomType>(
48 const this_pw_test::CustomType&, std::span<char> buffer) {
49 return string::Format(buffer, this_pw_test::CustomType::kToString);
Wyatt Heplerce9b9522019-11-11 10:45:48 -080050}
51
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070052} // namespace pw
53
54namespace pw {
Wyatt Heplerce9b9522019-11-11 10:45:48 -080055namespace {
56
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070057using this_pw_test::CustomType;
58
Wyatt Heplerce9b9522019-11-11 10:45:48 -080059TEST(StringBuilder, EmptyBuffer_SizeAndMaxSizeAreCorrect) {
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070060 StringBuilder sb(std::span<char>{});
Wyatt Heplerce9b9522019-11-11 10:45:48 -080061
62 EXPECT_TRUE(sb.empty());
63 EXPECT_EQ(0u, sb.size());
64 EXPECT_EQ(0u, sb.max_size());
65}
66
67using namespace std::literals::string_view_literals;
68
69constexpr std::string_view kNoTouch = "DO NOT TOUCH\0VALUE SHOULD NOT CHANGE"sv;
70
71TEST(StringBuilder, EmptyBuffer_StreamOutput_WritesNothing) {
72 char buffer[kNoTouch.size()];
73 std::memcpy(buffer, kNoTouch.data(), sizeof(buffer));
74
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070075 StringBuilder sb(std::span(buffer, 0));
Wyatt Heplerce9b9522019-11-11 10:45:48 -080076
77 sb << CustomType() << " is " << 12345;
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070078 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -080079 EXPECT_EQ(kNoTouch, std::string_view(buffer, sizeof(buffer)));
80}
81
82TEST(StringBuilder, EmptyBuffer_Append_WritesNothing) {
83 char buffer[kNoTouch.size()];
84 std::memcpy(buffer, kNoTouch.data(), sizeof(buffer));
85
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070086 StringBuilder sb(std::span(buffer, 0));
Wyatt Heplerce9b9522019-11-11 10:45:48 -080087
88 EXPECT_FALSE(sb.append("Hello").ok());
89 EXPECT_EQ(kNoTouch, std::string_view(buffer, sizeof(buffer)));
90}
91
92TEST(StringBuilder, EmptyBuffer_Resize_WritesNothing) {
93 char buffer[kNoTouch.size()];
94 std::memcpy(buffer, kNoTouch.data(), sizeof(buffer));
95
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070096 StringBuilder sb(std::span(buffer, 0));
Wyatt Heplerce9b9522019-11-11 10:45:48 -080097
98 sb.resize(0);
99 EXPECT_TRUE(sb.ok());
100 EXPECT_EQ(kNoTouch, std::string_view(buffer, sizeof(buffer)));
101}
102
103TEST(StringBuilder, EmptyBuffer_AppendEmpty_ResourceExhausted) {
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -0700104 StringBuilder sb(std::span<char>{});
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800105 EXPECT_EQ(OkStatus(), sb.last_status());
106 EXPECT_EQ(OkStatus(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800107
108 sb << "";
109
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700110 EXPECT_EQ(Status::ResourceExhausted(), sb.last_status());
111 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800112}
113
114TEST(StringBuilder, Status_StartsOk) {
115 StringBuffer<16> sb;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800116 EXPECT_EQ(OkStatus(), sb.status());
117 EXPECT_EQ(OkStatus(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800118}
119
120TEST(StringBuilder, Status_StatusAndLastStatusUpdate) {
121 StringBuffer<16> sb;
122 sb << "Well, if only there were enough room in here for this string";
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700123 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
124 EXPECT_EQ(Status::ResourceExhausted(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800125
126 sb.resize(1029);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700127 EXPECT_EQ(Status::OutOfRange(), sb.status());
128 EXPECT_EQ(Status::OutOfRange(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800129
130 sb << "";
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700131 EXPECT_EQ(Status::OutOfRange(), sb.status());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800132 EXPECT_EQ(OkStatus(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800133}
134
135TEST(StringBuilder, Status_ClearStatus_SetsStatuesToOk) {
136 StringBuffer<2> sb = MakeString<2>("Won't fit!!!!!");
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700137 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
138 EXPECT_EQ(Status::ResourceExhausted(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800139
140 sb.clear_status();
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800141 EXPECT_EQ(OkStatus(), sb.status());
142 EXPECT_EQ(OkStatus(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800143}
144
145TEST(StringBuilder, StreamOutput_OutputSelf) {
146 auto sb = MakeString<32>("echo!");
147 sb << sb;
148
149 EXPECT_STREQ("echo!echo!", sb.data());
150 EXPECT_EQ(10u, sb.size());
151}
152
153TEST(StringBuilder, PushBack) {
154 StringBuffer<12> sb;
155 sb.push_back('?');
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800156 EXPECT_EQ(OkStatus(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800157 EXPECT_EQ(1u, sb.size());
158 EXPECT_STREQ("?", sb.data());
159}
160
161TEST(StringBuilder, PushBack_Full) {
162 StringBuffer<1> sb;
163 sb.push_back('!');
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700164 EXPECT_EQ(Status::ResourceExhausted(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800165 EXPECT_EQ(0u, sb.size());
166}
167
168TEST(StringBuilder, PopBack) {
169 auto sb = MakeString<12>("Welcome!");
170 sb.pop_back();
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800171 EXPECT_EQ(OkStatus(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800172 EXPECT_EQ(7u, sb.size());
173 EXPECT_STREQ("Welcome", sb.data());
174}
175
176TEST(StringBuilder, PopBack_Empty) {
177 StringBuffer<12> sb;
178 sb.pop_back();
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700179 EXPECT_EQ(Status::OutOfRange(), sb.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800180 EXPECT_EQ(0u, sb.size());
181}
182
183TEST(StringBuilder, Append_NonTerminatedString) {
184 static char bad_string[256];
185 std::memset(bad_string, '?', sizeof(bad_string));
186
187 StringBuffer<6> sb;
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700188 EXPECT_EQ(Status::ResourceExhausted(), sb.append(bad_string).last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800189 EXPECT_STREQ("?????", sb.data());
190}
191
192TEST(StringBuilder, Append_Chars) {
193 StringBuffer<8> sb;
194
195 EXPECT_TRUE(sb.append(7, '?').ok());
196 EXPECT_STREQ("???????", sb.data());
197}
198
199TEST(StringBuilder, Append_Chars_Full) {
200 StringBuffer<8> sb;
201
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700202 EXPECT_EQ(Status::ResourceExhausted(), sb.append(8, '?').last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800203 EXPECT_STREQ("???????", sb.data());
204}
205
Wyatt Heplere5559002021-11-12 13:58:05 -0800206TEST(StringBuilder, Append_Chars_ToEmpty) {
207 StringBuilder sb(std::span<char>{});
208
209 EXPECT_EQ(Status::ResourceExhausted(), sb.append(1, '?').last_status());
210}
211
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800212TEST(StringBuilder, Append_PartialCString) {
213 StringBuffer<12> sb;
214 EXPECT_TRUE(sb.append("123456", 4).ok());
215 EXPECT_EQ(4u, sb.size());
216 EXPECT_STREQ("1234", sb.data());
217}
218
219TEST(StringBuilder, Append_CString) {
220 auto sb = MakeString("hello");
221 EXPECT_TRUE(sb.append(" goodbye").ok());
222 EXPECT_STREQ("hello goodbye", sb.data());
223 EXPECT_EQ(13u, sb.size());
224}
225
226TEST(StringBuilder, Append_CString_Full) {
227 auto sb = MakeString<6>("hello");
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700228 EXPECT_EQ(Status::ResourceExhausted(), sb.append("890123", 1).last_status());
229 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800230 EXPECT_EQ(sb.max_size(), sb.size());
231 EXPECT_STREQ("hello", sb.data());
232}
233
234TEST(StringBuilder, Append_StringView) {
235 auto sb = MakeString<32>("hello");
236 EXPECT_TRUE(sb.append("???"sv).ok());
237 EXPECT_EQ("hello???"sv, sb);
238}
239
240TEST(StringBuilder, Append_StringView_Substring) {
241 auto sb = MakeString<32>("I like ");
242 EXPECT_TRUE(sb.append("your shoes!!!"sv, 5, 5).ok());
243 EXPECT_EQ("I like shoes"sv, sb);
244}
245
246TEST(StringBuilder, Append_StringView_RemainingSubstring) {
247 auto sb = MakeString<32>("I like ");
248 EXPECT_TRUE(sb.append("your shoes!!!"sv, 5).ok());
249 EXPECT_EQ("I like shoes!!!"sv, sb);
250}
251
252TEST(StringBuilder, Resize_Smaller) {
253 auto sb = MakeString<12>("Four");
254 sb.resize(2);
255 EXPECT_TRUE(sb.ok());
256 EXPECT_EQ(2u, sb.size());
257 EXPECT_STREQ("Fo", sb.data());
258}
259
260TEST(StringBuilder, Resize_Clear) {
261 auto sb = MakeString<12>("Four");
262 sb.resize(0);
263 EXPECT_TRUE(sb.ok());
264 EXPECT_EQ(0u, sb.size());
265 EXPECT_STREQ("", sb.data());
266}
267
268TEST(StringBuilder, Resize_Larger_Fails) {
269 auto sb = MakeString<12>("Four");
270 EXPECT_EQ(4u, sb.size());
271 sb.resize(10);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700272 EXPECT_EQ(sb.status(), Status::OutOfRange());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800273 EXPECT_EQ(4u, sb.size());
274}
275
276TEST(StringBuilder, Resize_LargerThanCapacity_Fails) {
277 auto sb = MakeString<12>("Four");
278 sb.resize(1234);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700279 EXPECT_EQ(sb.status(), Status::OutOfRange());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800280 EXPECT_EQ(4u, sb.size());
281 EXPECT_STREQ("Four", sb.data());
282}
283
284TEST(StringBuilder, Format_Normal) {
Armando Montanez0693c382020-08-05 14:56:44 -0700285 std::byte buffer[64];
286 StringBuilder sb(buffer);
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800287 EXPECT_TRUE(sb.Format("0x%x", 0xabc).ok());
288 EXPECT_STREQ("0xabc", sb.data());
289
290 sb << "def";
291
292 EXPECT_TRUE(sb.Format("GHI").ok());
293 EXPECT_STREQ("0xabcdefGHI", sb.data());
294}
295
296TEST(StringBuilder, Format_ExhaustBuffer) {
297 StringBuffer<6> sb;
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700298 EXPECT_EQ(Status::ResourceExhausted(), sb.Format("012345").status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800299
300 EXPECT_STREQ("01234", sb.data());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700301 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800302}
303
304TEST(StringBuilder, StreamOutput_MultipleTypes) {
305 constexpr const char* kExpected = "This is -1true example\n of this";
306 constexpr const char* kExample = "example";
307
308 StringBuffer<64> sb;
309 sb << "This is " << -1 << true << ' ' << kExample << '\n' << " of this";
310
311 EXPECT_STREQ(kExpected, sb.data());
312 EXPECT_EQ(std::strlen(kExpected), sb.size());
313}
314
315TEST(StringBuilder, StreamOutput_FullBufferIgnoresExtraStrings) {
316 StringBuffer<6> sb;
317 EXPECT_EQ(5u, sb.max_size()); // max_size() excludes the null terminator
318
319 sb << 1 - 1;
320 EXPECT_TRUE(sb.ok());
321 EXPECT_STREQ("0", sb.data());
322
323 sb << true << "Now it's way " << static_cast<unsigned char>(2) << " long";
324 EXPECT_FALSE(sb.ok());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700325 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800326 EXPECT_STREQ("0true", sb.data());
327}
328
329TEST(StringBuilder, StreamOutput_ExhaustBuffer_InOneString) {
330 StringBuffer<9> sb;
331 EXPECT_EQ(8u, sb.max_size());
332
333 sb << "0123456789"; // write 10 chars
334 EXPECT_FALSE(sb.ok());
335 EXPECT_STREQ("01234567", sb.data()); // only can fit 8
336 EXPECT_EQ(8u, sb.size());
337
338 sb << "no"
339 << " more "
340 << "room" << '?';
341 EXPECT_STREQ("01234567", sb.data());
342}
343
344TEST(StringBuilder, StreamOutput_ExhaustBuffer_InTwoStrings) {
345 StringBuffer<4> sb;
346
347 sb << "01"; // fill 3/4 of buffer
348 EXPECT_EQ(2u, sb.size());
349 sb << "234";
350 EXPECT_STREQ("012", sb.data());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700351 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800352 EXPECT_EQ(3u, sb.size());
353}
354
355TEST(StringBuilder, StreamOutput_NonTerminatedString) {
356 static char bad_string[256];
357 std::memset(bad_string, '?', sizeof(bad_string));
358
359 StringBuffer<6> sb;
360 sb << "hey" << bad_string;
361
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700362 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800363 EXPECT_STREQ("hey??", sb.data());
364}
365
366TEST(StringBuilder, SteamOutput_StringView) {
367 StringBuffer<6> buffer;
368 constexpr std::string_view hello("hello");
369
370 buffer << hello;
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800371 EXPECT_EQ(OkStatus(), buffer.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800372 EXPECT_STREQ("hello", buffer.data());
373}
374
375TEST(StringBuilder, StreamOutput_EmptyStringView) {
376 StringBuffer<4> buffer;
377 buffer << "hi" << std::string_view() << "!";
378 EXPECT_TRUE(buffer.ok());
379 EXPECT_STREQ("hi!", buffer.data());
380}
381
Armando Montanez30c5d382021-11-29 12:26:09 -0800382TEST(StringBuilder, StreamOutput_ByteArray) {
Armando Montanez1cbc49a2021-11-19 18:30:27 -0800383 StringBuffer<7> buffer;
384 std::array<std::byte, 3> data{
385 {std::byte(0xc8), std::byte(0x02), std::byte(0x41)}};
386 buffer << data;
387 EXPECT_EQ(buffer.status(), OkStatus());
388 EXPECT_STREQ("c80241", buffer.data());
389}
390
Armando Montanez30c5d382021-11-29 12:26:09 -0800391TEST(StringBuilder, StreamOutput_ByteSpan) {
392 StringBuffer<11> buffer;
393 std::array<std::byte, 5> data{{std::byte(0),
394 std::byte(0xc8),
395 std::byte(0x02),
396 std::byte(0x41),
397 std::byte(0xe0)}};
398 buffer << std::as_bytes(std::span(data));
399 EXPECT_EQ(buffer.status(), OkStatus());
400 EXPECT_STREQ("00c80241e0", buffer.data());
401}
402
Armando Montanez1cbc49a2021-11-19 18:30:27 -0800403TEST(StringBuilder, StreamOutput_ByteSpanOutOfSpace) {
404 StringBuffer<4> buffer;
405 std::array<uint8_t, 3> data{{0xc8, 0x02, 0x41}};
Armando Montanez30c5d382021-11-29 12:26:09 -0800406 buffer << std::as_bytes(std::span(data));
Armando Montanez1cbc49a2021-11-19 18:30:27 -0800407 EXPECT_EQ(buffer.status(), Status::ResourceExhausted());
408 EXPECT_STREQ("", buffer.data());
409}
410
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800411TEST(StringBuffer, Assign) {
412 StringBuffer<10> one;
413 StringBuffer<10> two;
414
415 one << "What";
416 ASSERT_STREQ("What", one.data());
417 two = one;
418 EXPECT_STREQ("What", two.data());
419 EXPECT_NE(one.data(), two.data());
420 one << " the";
421 two << " heck";
422
423 EXPECT_STREQ("What the", one.data());
424 EXPECT_STREQ("What heck", two.data());
425
426 two << "0123456789";
427 ASSERT_STREQ("What heck", two.data());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700428 ASSERT_EQ(Status::ResourceExhausted(), two.status());
429 ASSERT_EQ(Status::ResourceExhausted(), two.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800430
431 one = two;
432 EXPECT_STREQ("What heck", one.data());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700433 EXPECT_EQ(Status::ResourceExhausted(), one.status());
434 EXPECT_EQ(Status::ResourceExhausted(), one.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800435
436 StringBuffer<12> three;
437 three = two;
438 EXPECT_STREQ(three.data(), two.data());
439 EXPECT_EQ(three.size(), two.size());
440}
441
442TEST(StringBuffer, CopyConstructFromSameSize) {
443 StringBuffer<10> one;
444
445 one << "What";
446 ASSERT_STREQ("What", one.data());
447 StringBuffer<10> two(one);
448 EXPECT_STREQ("What", two.data());
449 EXPECT_NE(one.data(), two.data());
450 one << " the";
451 two << " heck";
452
453 EXPECT_STREQ("What the", one.data());
454 EXPECT_STREQ("What heck", two.data());
455
456 two << "0123456789";
457 two << "";
458 ASSERT_STREQ("What heck", two.data());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700459 ASSERT_EQ(Status::ResourceExhausted(), two.status());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800460 ASSERT_EQ(OkStatus(), two.last_status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800461}
462
463TEST(StringBuffer, CopyConstructFromSmaller) {
464 StringBuffer<10> one = MakeString<10>("You are the chosen one.");
465 StringBuffer<12> two(one);
466
467 EXPECT_STREQ("You are t", two.data());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700468 EXPECT_EQ(Status::ResourceExhausted(), two.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800469}
470
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -0700471TEST(StringBuilder, Object) {
472 StringBuffer<64> sb;
473 sb << CustomType();
474
475 EXPECT_STREQ(CustomType::kToString, sb.data());
476 EXPECT_EQ(std::strlen(CustomType::kToString), sb.size());
477}
478
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800479TEST(MakeString, Object) {
480 CustomType custom;
481 const auto sb = MakeString<64>(custom);
482
483 EXPECT_STREQ(CustomType::kToString, sb.data());
484 EXPECT_EQ(std::strlen(CustomType::kToString), sb.size());
485}
486
487TEST(MakeString, IntegerTypes) {
488 EXPECT_STREQ("0123-4567",
489 MakeString(0ll,
490 1u,
491 2l,
492 3,
493 -4,
494 static_cast<unsigned short>(5),
495 static_cast<short>(6),
496 static_cast<unsigned char>(7))
497 .data());
498}
499
500TEST(MakeString, Char) {
501 EXPECT_STREQ("a b c", MakeString('a', ' ', 'b', ' ', 'c').data());
502}
503
504TEST(MakeString, Float) { EXPECT_STREQ("-inf", MakeString(-INFINITY).data()); }
505
506TEST(MakeString, Pointer_Null) {
507 EXPECT_STREQ("(null)", MakeString(nullptr).data());
508 EXPECT_STREQ("(null)", MakeString(static_cast<void*>(nullptr)).data());
509}
510
511TEST(MakeString, Pointer_NonNull) {
512 EXPECT_STREQ("1", MakeString(reinterpret_cast<void*>(0x1)).data());
513 EXPECT_STREQ("123", MakeString(reinterpret_cast<int*>(0x123)).data());
514}
515
516TEST(MakeString, Pointer_CustomType) {
517 char expected[32] = {};
518
519 CustomType custom;
520 std::snprintf(expected,
521 sizeof(expected),
522 "%" PRIxPTR,
523 reinterpret_cast<uintptr_t>(&custom));
524
525 EXPECT_STREQ(expected, MakeString(&custom).data());
526}
527
528TEST(MakeString, Bool) {
529 EXPECT_STREQ("true", MakeString(true).data());
530 EXPECT_STREQ("false", MakeString(false).data());
531}
532
533TEST(MakeString, MutableString) {
534 char chars[] = {'C', 'o', 'o', 'l', '\0'};
535 EXPECT_STREQ("Cool?", MakeString(chars, "?").data());
536}
537
538TEST(MakeString, Empty_IsEmpty) { EXPECT_TRUE(MakeString().empty()); }
539
540constexpr char kLongestString[] = "18446744073709551615"; // largest uint64_t
541
542TEST(MakeString, DefaultSizeString_FitsWholeString) {
543 EXPECT_STREQ(
544 kLongestString,
545 MakeString(184, "467", u'\x04', "40", '7', '3', '7', "0", "", 955ul, 1615)
546 .data());
547}
548
549TEST(MakeString, LargerThanDefaultSize_Truncates) {
550 auto sb = MakeString("1844674407", 3709551615, 123456);
551
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700552 EXPECT_EQ(Status::ResourceExhausted(), sb.status());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800553 EXPECT_STREQ(kLongestString, sb.data());
554}
555
556TEST(MakeString, StringLiteral_ResizesToFitWholeLiteral) {
557 EXPECT_STREQ("", MakeString().data());
558
Prashanth Swaminathan89dd0532021-03-04 19:56:47 -0800559 [[maybe_unused]] auto normal = MakeString("");
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800560 static_assert(normal.max_size() == decltype(MakeString(1))::max_size());
Prashanth Swaminathan659a5c52021-02-05 21:11:47 -0800561 EXPECT_EQ(normal.max_size(), decltype(MakeString(1))::max_size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800562
Prashanth Swaminathan89dd0532021-03-04 19:56:47 -0800563 [[maybe_unused]] auto resized =
564 MakeString("This string is reeeeeeeeeaaaaallly long!!!!!");
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800565 static_assert(resized.max_size() > decltype(MakeString(1))::max_size());
566 static_assert(resized.max_size() ==
567 sizeof("This string is reeeeeeeeeaaaaallly long!!!!!") - 1);
Prashanth Swaminathan659a5c52021-02-05 21:11:47 -0800568 EXPECT_GT(resized.max_size(), decltype(MakeString(1))::max_size());
569 EXPECT_EQ(resized.max_size(),
570 sizeof("This string is reeeeeeeeeaaaaallly long!!!!!") - 1);
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800571}
572
573TEST(MakeString, StringLiteral_UsesLongerFixedSize) {
574 auto fixed_size = MakeString<64>("");
575 static_assert(fixed_size.max_size() == 63u);
576 EXPECT_EQ(fixed_size.max_size(), 63u);
577 EXPECT_STREQ("", fixed_size.data());
578}
579
580TEST(MakeString, StringLiteral_TruncatesShorterFixedSize) {
581 EXPECT_STREQ("Goo", MakeString<4>("Google").data());
582 EXPECT_STREQ("Google", MakeString<7>("Google").data());
583 EXPECT_EQ(MakeString().max_size(), MakeString("Google").max_size());
584 EXPECT_STREQ("Google", MakeString("Google").data());
585}
586
587TEST(MakeString, DefaultSize_FitsMaxAndMinInts) {
588 EXPECT_STREQ("-9223372036854775808",
589 MakeString(std::numeric_limits<int64_t>::min()).data());
590 EXPECT_STREQ("18446744073709551615",
591 MakeString(std::numeric_limits<uint64_t>::max()).data());
592}
593
594TEST(MakeString, OutputToTemporaryStringBuffer) {
595 EXPECT_STREQ("hello", (MakeString<6>("hello ") << "world").data());
596 EXPECT_STREQ("hello world", (MakeString("hello ") << "world").data());
597}
598
599// Test MakeString's default size calculations.
600template <typename... Args>
601constexpr size_t DefaultStringBufferSize(Args&&...) {
602 return string_internal::DefaultStringBufferSize<Args...>();
603}
604
605// Default sizes are rounded up to 24 bytes.
606static_assert(DefaultStringBufferSize("") == 24);
607static_assert(DefaultStringBufferSize("123") == 24);
608static_assert(DefaultStringBufferSize("123", "456", "78901234567890") == 24);
609static_assert(DefaultStringBufferSize("1234567890", "1234567890", "123") == 24);
610static_assert(DefaultStringBufferSize(1234, 5678, 9012) == 24);
611
612// The buffer is sized to fix strings needing more than 24 bytes.
613static_assert(DefaultStringBufferSize("1234567890", "1234567890", "1234") ==
614 25);
615static_assert(DefaultStringBufferSize("1234567890", "1234567890", "12345") ==
616 26);
617static_assert(DefaultStringBufferSize("1234567890", "1234567890", "12345678") ==
618 29);
619
620// Four bytes are allocated for each non-string argument.
621static_assert(DefaultStringBufferSize(1234, 5678, 9012, 3456, 7890, 1234) ==
622 25);
623static_assert(DefaultStringBufferSize('a', nullptr, 'b', 4, 5, 6, 7, 8) == 33);
624
Wyatt Hepler0435efe2021-03-01 14:00:36 -0800625struct SomeCustomType {};
626
627StringBuilder& operator<<(StringBuilder& sb, const SomeCustomType&) {
628 return sb << "SomeCustomType was here!";
629}
630
631TEST(StringBuilder, ShiftOperatorOverload_SameNamsepace) {
632 pw::StringBuffer<48> buffer;
633 buffer << SomeCustomType{};
634
635 EXPECT_STREQ("SomeCustomType was here!", buffer.c_str());
636}
637
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800638} // namespace
639} // namespace pw
Wyatt Hepler0435efe2021-03-01 14:00:36 -0800640
641namespace some_other_ns {
642
643struct MyCustomType {
644 int item;
645};
646
647pw::StringBuilder& operator<<(pw::StringBuilder& sb,
648 const MyCustomType& value) {
649 return sb << "MyCustomType(" << value.item << ')';
650}
651
652} // namespace some_other_ns
653
654namespace pw_test_namespace {
655
656TEST(StringBuilder, ShiftOperatorOverload_DifferentNamsepace) {
657 pw::StringBuffer<48> buffer;
658 buffer << "This is " << some_other_ns::MyCustomType{1138};
659
660 EXPECT_STREQ("This is MyCustomType(1138)", buffer.data());
661}
662
663} // namespace pw_test_namespace