blob: 19d493173349ea64a84a6835207f5e70da71a02d [file] [log] [blame]
Wyatt Hepler58823c12019-11-13 14:27:31 -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 Hepler58823c12019-11-13 14:27:31 -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 Hepler58823c12019-11-13 14:27:31 -080014
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"
Wyatt Heplerce9b9522019-11-11 10:45:48 -080025#include "pw_string/type_to_string.h"
Wyatt Hepler58823c12019-11-13 14:27:31 -080026
27namespace pw {
28
29struct 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
42StatusWithSize ToString(const CustomType&, const span<char>& buffer) {
43 int result =
44 std::snprintf(buffer.data(), buffer.size(), CustomType::kToString);
45 if (result < 0) {
Wyatt Heplerf7078802020-02-25 13:50:05 -080046 return StatusWithSize::UNKNOWN;
Wyatt Hepler58823c12019-11-13 14:27:31 -080047 }
48 if (static_cast<size_t>(result) < buffer.size()) {
49 return StatusWithSize(result);
50 }
51 return StatusWithSize(Status::RESOURCE_EXHAUSTED,
52 buffer.empty() ? 0u : buffer.size() - 1);
53}
54
55namespace {
56
57char buffer[128] = {};
58char expected[128] = {};
59
60TEST(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
68TEST(ToString, Char) {
69 EXPECT_EQ(1u, ToString('%', buffer).size());
70 EXPECT_STREQ("%", buffer);
71}
72
73template <typename T>
74constexpr T kInteger = 127;
75
76TEST(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
Wyatt Hepler38426d72019-11-20 10:21:55 -080099TEST(ToString, Integer_EmptyBuffer_WritesNothing) {
100 auto result = ToString(-1234, span(buffer, 0));
101 EXPECT_EQ(0u, result.size());
102 EXPECT_EQ(Status::RESOURCE_EXHAUSTED, result.status());
103}
104
Wyatt Hepler58823c12019-11-13 14:27:31 -0800105TEST(ToString, Integer_BufferTooSmall_WritesNullTerminator) {
106 auto result = ToString(-1234, span(buffer, 5));
107 EXPECT_EQ(0u, result.size());
108 EXPECT_FALSE(result.ok());
109 EXPECT_STREQ("", buffer);
110}
111
112TEST(ToString, Float) {
113 EXPECT_EQ(1u, ToString(0.0f, buffer).size());
114 EXPECT_STREQ("0", buffer);
115 EXPECT_EQ(3u, ToString(INFINITY, buffer).size());
116 EXPECT_STREQ("inf", buffer);
117 EXPECT_EQ(4u, ToString(-NAN, buffer).size());
118 EXPECT_STREQ("-NaN", buffer);
119}
120
121TEST(ToString, Pointer_NonNull_WritesValue) {
122 CustomType custom;
123 const size_t length = std::snprintf(expected,
124 sizeof(expected),
Wyatt Hepler190fecc2019-11-13 18:10:57 -0800125 "%" PRIxPTR,
Wyatt Hepler58823c12019-11-13 14:27:31 -0800126 reinterpret_cast<intptr_t>(&custom));
127
128 EXPECT_EQ(length, ToString(&custom, buffer).size());
129 EXPECT_STREQ(expected, buffer);
130 EXPECT_EQ(length, ToString(static_cast<void*>(&custom), buffer).size());
131 EXPECT_STREQ(expected, buffer);
132 EXPECT_EQ(1u, ToString(reinterpret_cast<int*>(4), buffer).size());
133 EXPECT_STREQ("4", buffer);
134}
135
Wyatt Hepler38426d72019-11-20 10:21:55 -0800136TEST(ToString, Pointer_Nullptr_WritesNull) {
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800137 EXPECT_EQ(string::kNullPointerString.size(),
138 ToString(nullptr, buffer).size());
139 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler38426d72019-11-20 10:21:55 -0800140}
141
142TEST(ToString, Pointer_NullValuedPointer_WritesNull) {
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800143 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler58823c12019-11-13 14:27:31 -0800144 ToString(static_cast<const CustomType*>(nullptr), buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800145 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler38426d72019-11-20 10:21:55 -0800146}
147
148TEST(ToString, Pointer_NullValuedCString_WritesNull) {
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800149 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler38426d72019-11-20 10:21:55 -0800150 ToString(static_cast<char*>(nullptr), buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800151 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler38426d72019-11-20 10:21:55 -0800152
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800153 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler38426d72019-11-20 10:21:55 -0800154 ToString(static_cast<const char*>(nullptr), buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800155 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler58823c12019-11-13 14:27:31 -0800156}
157
158TEST(ToString, String_Literal) {
159 EXPECT_EQ(0u, ToString("", buffer).size());
160 EXPECT_STREQ("", buffer);
161 EXPECT_EQ(5u, ToString("hello", buffer).size());
162 EXPECT_STREQ("hello", buffer);
163}
164
Wyatt Hepler38426d72019-11-20 10:21:55 -0800165TEST(ToString, String_Pointer) {
166 EXPECT_EQ(0u, ToString(static_cast<const char*>(""), buffer).size());
167 EXPECT_STREQ("", buffer);
168 EXPECT_EQ(5u, ToString(static_cast<const char*>("hello"), buffer).size());
169 EXPECT_STREQ("hello", buffer);
170}
171
Wyatt Hepler58823c12019-11-13 14:27:31 -0800172TEST(ToString, String_MutableBuffer) {
173 char chars[] = {'C', 'o', 'o', 'l', '\0'};
174 EXPECT_EQ(sizeof(chars) - 1, ToString(chars, buffer).size());
175 EXPECT_STREQ("Cool", buffer);
176}
177
Wyatt Hepler38426d72019-11-20 10:21:55 -0800178TEST(ToString, String_MutablePointer) {
179 char chars[] = {'b', 'o', 'o', 'l', '\0'};
180 EXPECT_EQ(sizeof(chars) - 1,
181 ToString(static_cast<char*>(chars), buffer).size());
182 EXPECT_STREQ("bool", buffer);
183}
184
Wyatt Hepler58823c12019-11-13 14:27:31 -0800185TEST(ToString, Object) {
186 CustomType custom;
187 EXPECT_EQ(std::strlen(CustomType::kToString),
188 ToString(custom, buffer).size());
189 EXPECT_STREQ(CustomType::kToString, buffer);
190}
191
192enum Foo : uint8_t {
193 BAR = 32,
194 BAZ = 100,
195};
196
197TEST(ToString, Enum) {
198 EXPECT_EQ(2u, ToString(Foo::BAR, buffer).size());
199 EXPECT_STREQ("32", buffer);
200
201 EXPECT_EQ(3u, ToString(Foo::BAZ, buffer).size());
202 EXPECT_STREQ("100", buffer);
203}
204
205TEST(ToString, Status) {
206 EXPECT_EQ(2u, ToString(Status(), buffer).size());
207 EXPECT_STREQ(Status().str(), buffer);
208}
209
210TEST(ToString, StatusCode) {
211 EXPECT_EQ(2u, ToString(Status::UNAVAILABLE, buffer).size());
212 EXPECT_STREQ("14", buffer);
213}
214
215TEST(ToString, StdArrayAsBuffer) {
216 std::array<char, 128> test_buffer;
217 EXPECT_EQ(5u, ToString(false, test_buffer).size());
218 EXPECT_STREQ("false", test_buffer.data());
219 EXPECT_EQ(2u, ToString("Hi", test_buffer).size());
220 EXPECT_STREQ("Hi", test_buffer.data());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800221 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler38426d72019-11-20 10:21:55 -0800222 ToString(static_cast<void*>(nullptr), test_buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800223 EXPECT_EQ(string::kNullPointerString, test_buffer.data());
Wyatt Hepler58823c12019-11-13 14:27:31 -0800224}
225
226TEST(ToString, StringView) {
227 std::string_view view = "cool";
228 EXPECT_EQ(4u, ToString(view, buffer).size());
229 EXPECT_STREQ("cool", buffer);
230}
231
232TEST(ToString, StringView_TooSmall_Truncates) {
233 std::string_view view = "kale!";
234 EXPECT_EQ(3u, ToString(view, span(buffer, 4)).size());
235 EXPECT_STREQ("kal", buffer);
236}
237
238TEST(ToString, StringView_EmptyBuffer_WritesNothing) {
239 constexpr char kOriginal[] = {'@', '#', '$', '%'};
240 char test_buffer[sizeof(kOriginal)];
241 std::memcpy(test_buffer, kOriginal, sizeof(kOriginal));
242
243 EXPECT_EQ(0u,
244 ToString(std::string_view("Hello!"), span(test_buffer, 0)).size());
245 ASSERT_EQ(0, std::memcmp(kOriginal, test_buffer, sizeof(kOriginal)));
246}
247
248TEST(ToString, StdString) {
249 EXPECT_EQ(5u, ToString(std::string("Whoa!"), buffer).size());
250 EXPECT_STREQ("Whoa!", buffer);
251
252 EXPECT_EQ(0u, ToString(std::string(), buffer).size());
253 EXPECT_STREQ("", buffer);
254}
255
256} // namespace
257} // namespace pw