1 // Copyright 2019 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
15 #include "pw_string/to_string.h"
23 #include "gtest/gtest.h"
24 #include "pw_status/status.h"
25 #include "pw_string/type_to_string.h"
33 static constexpr const char* kToString = "This is a CustomType";
35 CustomType() = default;
37 // Non-copyable to verify that ToString doesn't copy it.
38 CustomType(const CustomType&) = delete;
39 CustomType& operator=(const CustomType&) = delete;
42 StatusWithSize ToString(const CustomType&, std::span<char> buffer) {
44 std::snprintf(buffer.data(), buffer.size(), CustomType::kToString);
46 return StatusWithSize::Unknown();
48 if (static_cast<size_t>(result) < buffer.size()) {
49 return StatusWithSize(result);
51 return StatusWithSize::ResourceExhausted(buffer.empty() ? 0u
57 char buffer[128] = {};
58 char expected[128] = {};
60 TEST(ToString, Bool) {
61 const volatile bool b = true;
62 EXPECT_EQ(4u, ToString(b, buffer).size());
63 EXPECT_STREQ("true", buffer);
64 EXPECT_EQ(5u, ToString(false, buffer).size());
65 EXPECT_STREQ("false", buffer);
68 TEST(ToString, Char) {
69 EXPECT_EQ(1u, ToString('%', buffer).size());
70 EXPECT_STREQ("%", buffer);
74 constexpr T kInteger = 127;
76 TEST(ToString, Integer_AllTypesAreSupported) {
77 EXPECT_EQ(3u, ToString(kInteger<unsigned char>, buffer).size());
78 EXPECT_STREQ("127", buffer);
79 EXPECT_EQ(3u, ToString(kInteger<signed char>, buffer).size());
80 EXPECT_STREQ("127", buffer);
81 EXPECT_EQ(3u, ToString(kInteger<unsigned short>, buffer).size());
82 EXPECT_STREQ("127", buffer);
83 EXPECT_EQ(3u, ToString(kInteger<signed short>, buffer).size());
84 EXPECT_STREQ("127", buffer);
85 EXPECT_EQ(3u, ToString(kInteger<unsigned int>, buffer).size());
86 EXPECT_STREQ("127", buffer);
87 EXPECT_EQ(3u, ToString(kInteger<signed int>, buffer).size());
88 EXPECT_STREQ("127", buffer);
89 EXPECT_EQ(3u, ToString(kInteger<unsigned long>, buffer).size());
90 EXPECT_STREQ("127", buffer);
91 EXPECT_EQ(3u, ToString(kInteger<signed long>, buffer).size());
92 EXPECT_STREQ("127", buffer);
93 EXPECT_EQ(3u, ToString(kInteger<unsigned long long>, buffer).size());
94 EXPECT_STREQ("127", buffer);
95 EXPECT_EQ(3u, ToString(kInteger<signed long long>, buffer).size());
96 EXPECT_STREQ("127", buffer);
99 TEST(ToString, ScopedEnum) {
100 enum class MyEnum : short { kLuckyNumber = 8 };
102 auto result = ToString(MyEnum::kLuckyNumber, buffer);
103 EXPECT_EQ(1u, result.size());
104 EXPECT_EQ(OkStatus(), result.status());
105 EXPECT_STREQ("8", buffer);
108 TEST(ToString, Integer_EmptyBuffer_WritesNothing) {
109 auto result = ToString(-1234, std::span(buffer, 0));
110 EXPECT_EQ(0u, result.size());
111 EXPECT_EQ(Status::ResourceExhausted(), result.status());
114 TEST(ToString, Integer_BufferTooSmall_WritesNullTerminator) {
115 auto result = ToString(-1234, std::span(buffer, 5));
116 EXPECT_EQ(0u, result.size());
117 EXPECT_FALSE(result.ok());
118 EXPECT_STREQ("", buffer);
121 TEST(ToString, Float) {
122 EXPECT_EQ(1u, ToString(0.0f, buffer).size());
123 EXPECT_STREQ("0", buffer);
124 EXPECT_EQ(3u, ToString(INFINITY, buffer).size());
125 EXPECT_STREQ("inf", buffer);
126 EXPECT_EQ(4u, ToString(-NAN, buffer).size());
127 EXPECT_STREQ("-NaN", buffer);
130 TEST(ToString, Pointer_NonNull_WritesValue) {
132 const size_t length = std::snprintf(expected,
135 reinterpret_cast<intptr_t>(&custom));
137 EXPECT_EQ(length, ToString(&custom, buffer).size());
138 EXPECT_STREQ(expected, buffer);
139 EXPECT_EQ(length, ToString(static_cast<void*>(&custom), buffer).size());
140 EXPECT_STREQ(expected, buffer);
141 EXPECT_EQ(1u, ToString(reinterpret_cast<int*>(4), buffer).size());
142 EXPECT_STREQ("4", buffer);
145 TEST(ToString, Pointer_Nullptr_WritesNull) {
146 EXPECT_EQ(string::kNullPointerString.size(),
147 ToString(nullptr, buffer).size());
148 EXPECT_EQ(string::kNullPointerString, buffer);
151 TEST(ToString, Pointer_NullValuedPointer_WritesNull) {
152 EXPECT_EQ(string::kNullPointerString.size(),
153 ToString(static_cast<const CustomType*>(nullptr), buffer).size());
154 EXPECT_EQ(string::kNullPointerString, buffer);
157 TEST(ToString, Pointer_NullValuedCString_WritesNull) {
158 EXPECT_EQ(string::kNullPointerString.size(),
159 ToString(static_cast<char*>(nullptr), buffer).size());
160 EXPECT_EQ(string::kNullPointerString, buffer);
162 EXPECT_EQ(string::kNullPointerString.size(),
163 ToString(static_cast<const char*>(nullptr), buffer).size());
164 EXPECT_EQ(string::kNullPointerString, buffer);
167 TEST(ToString, String_Literal) {
168 EXPECT_EQ(0u, ToString("", buffer).size());
169 EXPECT_STREQ("", buffer);
170 EXPECT_EQ(5u, ToString("hello", buffer).size());
171 EXPECT_STREQ("hello", buffer);
174 TEST(ToString, String_Pointer) {
175 EXPECT_EQ(0u, ToString(static_cast<const char*>(""), buffer).size());
176 EXPECT_STREQ("", buffer);
177 EXPECT_EQ(5u, ToString(static_cast<const char*>("hello"), buffer).size());
178 EXPECT_STREQ("hello", buffer);
181 TEST(ToString, String_MutableBuffer) {
182 char chars[] = {'C', 'o', 'o', 'l', '\0'};
183 EXPECT_EQ(sizeof(chars) - 1, ToString(chars, buffer).size());
184 EXPECT_STREQ("Cool", buffer);
187 TEST(ToString, String_MutablePointer) {
188 char chars[] = {'b', 'o', 'o', 'l', '\0'};
189 EXPECT_EQ(sizeof(chars) - 1,
190 ToString(static_cast<char*>(chars), buffer).size());
191 EXPECT_STREQ("bool", buffer);
194 TEST(ToString, Object) {
196 EXPECT_EQ(std::strlen(CustomType::kToString),
197 ToString(custom, buffer).size());
198 EXPECT_STREQ(CustomType::kToString, buffer);
206 TEST(ToString, Enum) {
207 EXPECT_EQ(2u, ToString(Foo::BAR, buffer).size());
208 EXPECT_STREQ("32", buffer);
210 EXPECT_EQ(3u, ToString(Foo::BAZ, buffer).size());
211 EXPECT_STREQ("100", buffer);
214 TEST(ToString, Status) {
215 EXPECT_EQ(2u, ToString(Status(), buffer).size());
216 EXPECT_STREQ(Status().str(), buffer);
219 TEST(ToString, StatusCode) {
220 EXPECT_EQ(sizeof("UNAVAILABLE") - 1,
221 ToString(Status::Unavailable(), buffer).size());
222 EXPECT_STREQ("UNAVAILABLE", buffer);
225 TEST(ToString, StdArrayAsBuffer) {
226 std::array<char, 128> test_buffer;
227 EXPECT_EQ(5u, ToString(false, test_buffer).size());
228 EXPECT_STREQ("false", test_buffer.data());
229 EXPECT_EQ(2u, ToString("Hi", test_buffer).size());
230 EXPECT_STREQ("Hi", test_buffer.data());
231 EXPECT_EQ(string::kNullPointerString.size(),
232 ToString(static_cast<void*>(nullptr), test_buffer).size());
233 EXPECT_EQ(string::kNullPointerString, test_buffer.data());
236 TEST(ToString, StringView) {
237 std::string_view view = "cool";
238 EXPECT_EQ(4u, ToString(view, buffer).size());
239 EXPECT_STREQ("cool", buffer);
242 TEST(ToString, StringView_TooSmall_Truncates) {
243 std::string_view view = "kale!";
244 EXPECT_EQ(3u, ToString(view, std::span(buffer, 4)).size());
245 EXPECT_STREQ("kal", buffer);
248 TEST(ToString, StringView_EmptyBuffer_WritesNothing) {
249 constexpr char kOriginal[] = {'@', '#', '$', '%'};
250 char test_buffer[sizeof(kOriginal)];
251 std::memcpy(test_buffer, kOriginal, sizeof(kOriginal));
255 ToString(std::string_view("Hello!"), std::span(test_buffer, 0)).size());
256 ASSERT_EQ(0, std::memcmp(kOriginal, test_buffer, sizeof(kOriginal)));
259 TEST(ToString, StdString) {
260 EXPECT_EQ(5u, ToString(std::string("Whoa!"), buffer).size());
261 EXPECT_STREQ("Whoa!", buffer);
263 EXPECT_EQ(0u, ToString(std::string(), buffer).size());
264 EXPECT_STREQ("", buffer);