Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_string / to_string_test.cc
1 // Copyright 2019 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/to_string.h"
16
17 #include <array>
18 #include <cinttypes>
19 #include <cmath>
20 #include <cstring>
21 #include <string>
22
23 #include "gtest/gtest.h"
24 #include "pw_status/status.h"
25 #include "pw_string/type_to_string.h"
26
27 namespace pw {
28
29 struct CustomType {
30   unsigned a;
31   unsigned b;
32
33   static constexpr const char* kToString = "This is a CustomType";
34
35   CustomType() = default;
36
37   // Non-copyable to verify that ToString doesn't copy it.
38   CustomType(const CustomType&) = delete;
39   CustomType& operator=(const CustomType&) = delete;
40 };
41
42 StatusWithSize ToString(const CustomType&, std::span<char> buffer) {
43   int result =
44       std::snprintf(buffer.data(), buffer.size(), CustomType::kToString);
45   if (result < 0) {
46     return StatusWithSize::Unknown();
47   }
48   if (static_cast<size_t>(result) < buffer.size()) {
49     return StatusWithSize(result);
50   }
51   return StatusWithSize::ResourceExhausted(buffer.empty() ? 0u
52                                                           : buffer.size() - 1);
53 }
54
55 namespace {
56
57 char buffer[128] = {};
58 char expected[128] = {};
59
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);
66 }
67
68 TEST(ToString, Char) {
69   EXPECT_EQ(1u, ToString('%', buffer).size());
70   EXPECT_STREQ("%", buffer);
71 }
72
73 template <typename T>
74 constexpr T kInteger = 127;
75
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);
97 }
98
99 TEST(ToString, ScopedEnum) {
100   enum class MyEnum : short { kLuckyNumber = 8 };
101
102   auto result = ToString(MyEnum::kLuckyNumber, buffer);
103   EXPECT_EQ(1u, result.size());
104   EXPECT_EQ(OkStatus(), result.status());
105   EXPECT_STREQ("8", buffer);
106 }
107
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());
112 }
113
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);
119 }
120
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);
128 }
129
130 TEST(ToString, Pointer_NonNull_WritesValue) {
131   CustomType custom;
132   const size_t length = std::snprintf(expected,
133                                       sizeof(expected),
134                                       "%" PRIxPTR,
135                                       reinterpret_cast<intptr_t>(&custom));
136
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);
143 }
144
145 TEST(ToString, Pointer_Nullptr_WritesNull) {
146   EXPECT_EQ(string::kNullPointerString.size(),
147             ToString(nullptr, buffer).size());
148   EXPECT_EQ(string::kNullPointerString, buffer);
149 }
150
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);
155 }
156
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);
161
162   EXPECT_EQ(string::kNullPointerString.size(),
163             ToString(static_cast<const char*>(nullptr), buffer).size());
164   EXPECT_EQ(string::kNullPointerString, buffer);
165 }
166
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);
172 }
173
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);
179 }
180
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);
185 }
186
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);
192 }
193
194 TEST(ToString, Object) {
195   CustomType custom;
196   EXPECT_EQ(std::strlen(CustomType::kToString),
197             ToString(custom, buffer).size());
198   EXPECT_STREQ(CustomType::kToString, buffer);
199 }
200
201 enum Foo : uint8_t {
202   BAR = 32,
203   BAZ = 100,
204 };
205
206 TEST(ToString, Enum) {
207   EXPECT_EQ(2u, ToString(Foo::BAR, buffer).size());
208   EXPECT_STREQ("32", buffer);
209
210   EXPECT_EQ(3u, ToString(Foo::BAZ, buffer).size());
211   EXPECT_STREQ("100", buffer);
212 }
213
214 TEST(ToString, Status) {
215   EXPECT_EQ(2u, ToString(Status(), buffer).size());
216   EXPECT_STREQ(Status().str(), buffer);
217 }
218
219 TEST(ToString, StatusCode) {
220   EXPECT_EQ(sizeof("UNAVAILABLE") - 1,
221             ToString(Status::Unavailable(), buffer).size());
222   EXPECT_STREQ("UNAVAILABLE", buffer);
223 }
224
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());
234 }
235
236 TEST(ToString, StringView) {
237   std::string_view view = "cool";
238   EXPECT_EQ(4u, ToString(view, buffer).size());
239   EXPECT_STREQ("cool", buffer);
240 }
241
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);
246 }
247
248 TEST(ToString, StringView_EmptyBuffer_WritesNothing) {
249   constexpr char kOriginal[] = {'@', '#', '$', '%'};
250   char test_buffer[sizeof(kOriginal)];
251   std::memcpy(test_buffer, kOriginal, sizeof(kOriginal));
252
253   EXPECT_EQ(
254       0u,
255       ToString(std::string_view("Hello!"), std::span(test_buffer, 0)).size());
256   ASSERT_EQ(0, std::memcmp(kOriginal, test_buffer, sizeof(kOriginal)));
257 }
258
259 TEST(ToString, StdString) {
260   EXPECT_EQ(5u, ToString(std::string("Whoa!"), buffer).size());
261   EXPECT_STREQ("Whoa!", buffer);
262
263   EXPECT_EQ(0u, ToString(std::string(), buffer).size());
264   EXPECT_STREQ("", buffer);
265 }
266
267 }  // namespace
268 }  // namespace pw