blob: 347010acdd327a643e0f31cc79f180c58471646e [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
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -070042StatusWithSize ToString(const CustomType&, std::span<char> buffer) {
Wyatt Hepler58823c12019-11-13 14:27:31 -080043 int result =
44 std::snprintf(buffer.data(), buffer.size(), CustomType::kToString);
45 if (result < 0) {
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070046 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 }
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070051 return StatusWithSize::ResourceExhausted(buffer.empty() ? 0u
52 : buffer.size() - 1);
Wyatt Hepler58823c12019-11-13 14:27:31 -080053}
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 Heplera2a63d32020-03-18 13:11:58 -070099TEST(ToString, ScopedEnum) {
100 enum class MyEnum : short { kLuckyNumber = 8 };
101
102 auto result = ToString(MyEnum::kLuckyNumber, buffer);
103 EXPECT_EQ(1u, result.size());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800104 EXPECT_EQ(OkStatus(), result.status());
Wyatt Heplera2a63d32020-03-18 13:11:58 -0700105 EXPECT_STREQ("8", buffer);
106}
107
Wyatt Hepler38426d72019-11-20 10:21:55 -0800108TEST(ToString, Integer_EmptyBuffer_WritesNothing) {
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -0700109 auto result = ToString(-1234, std::span(buffer, 0));
Wyatt Hepler38426d72019-11-20 10:21:55 -0800110 EXPECT_EQ(0u, result.size());
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700111 EXPECT_EQ(Status::ResourceExhausted(), result.status());
Wyatt Hepler38426d72019-11-20 10:21:55 -0800112}
113
Wyatt Hepler58823c12019-11-13 14:27:31 -0800114TEST(ToString, Integer_BufferTooSmall_WritesNullTerminator) {
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -0700115 auto result = ToString(-1234, std::span(buffer, 5));
Wyatt Hepler58823c12019-11-13 14:27:31 -0800116 EXPECT_EQ(0u, result.size());
117 EXPECT_FALSE(result.ok());
118 EXPECT_STREQ("", buffer);
119}
120
121TEST(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
130TEST(ToString, Pointer_NonNull_WritesValue) {
131 CustomType custom;
132 const size_t length = std::snprintf(expected,
133 sizeof(expected),
Wyatt Hepler190fecc2019-11-13 18:10:57 -0800134 "%" PRIxPTR,
Wyatt Hepler58823c12019-11-13 14:27:31 -0800135 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
Wyatt Hepler38426d72019-11-20 10:21:55 -0800145TEST(ToString, Pointer_Nullptr_WritesNull) {
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800146 EXPECT_EQ(string::kNullPointerString.size(),
147 ToString(nullptr, buffer).size());
148 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler38426d72019-11-20 10:21:55 -0800149}
150
151TEST(ToString, Pointer_NullValuedPointer_WritesNull) {
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800152 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler58823c12019-11-13 14:27:31 -0800153 ToString(static_cast<const CustomType*>(nullptr), buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800154 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler38426d72019-11-20 10:21:55 -0800155}
156
157TEST(ToString, Pointer_NullValuedCString_WritesNull) {
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800158 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler38426d72019-11-20 10:21:55 -0800159 ToString(static_cast<char*>(nullptr), buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800160 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler38426d72019-11-20 10:21:55 -0800161
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800162 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler38426d72019-11-20 10:21:55 -0800163 ToString(static_cast<const char*>(nullptr), buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800164 EXPECT_EQ(string::kNullPointerString, buffer);
Wyatt Hepler58823c12019-11-13 14:27:31 -0800165}
166
167TEST(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
Wyatt Hepler38426d72019-11-20 10:21:55 -0800174TEST(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
Wyatt Hepler58823c12019-11-13 14:27:31 -0800181TEST(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
Wyatt Hepler38426d72019-11-20 10:21:55 -0800187TEST(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
Wyatt Hepler58823c12019-11-13 14:27:31 -0800194TEST(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
201enum Foo : uint8_t {
202 BAR = 32,
203 BAZ = 100,
204};
205
206TEST(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
214TEST(ToString, Status) {
215 EXPECT_EQ(2u, ToString(Status(), buffer).size());
216 EXPECT_STREQ(Status().str(), buffer);
217}
218
219TEST(ToString, StatusCode) {
Wyatt Heplerc0af5542020-06-16 13:21:47 -0700220 EXPECT_EQ(sizeof("UNAVAILABLE") - 1,
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700221 ToString(Status::Unavailable(), buffer).size());
Wyatt Heplerc0af5542020-06-16 13:21:47 -0700222 EXPECT_STREQ("UNAVAILABLE", buffer);
Wyatt Hepler58823c12019-11-13 14:27:31 -0800223}
224
225TEST(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());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800231 EXPECT_EQ(string::kNullPointerString.size(),
Wyatt Hepler38426d72019-11-20 10:21:55 -0800232 ToString(static_cast<void*>(nullptr), test_buffer).size());
Wyatt Heplerce9b9522019-11-11 10:45:48 -0800233 EXPECT_EQ(string::kNullPointerString, test_buffer.data());
Wyatt Hepler58823c12019-11-13 14:27:31 -0800234}
235
236TEST(ToString, StringView) {
237 std::string_view view = "cool";
238 EXPECT_EQ(4u, ToString(view, buffer).size());
239 EXPECT_STREQ("cool", buffer);
240}
241
242TEST(ToString, StringView_TooSmall_Truncates) {
243 std::string_view view = "kale!";
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -0700244 EXPECT_EQ(3u, ToString(view, std::span(buffer, 4)).size());
Wyatt Hepler58823c12019-11-13 14:27:31 -0800245 EXPECT_STREQ("kal", buffer);
246}
247
248TEST(ToString, StringView_EmptyBuffer_WritesNothing) {
249 constexpr char kOriginal[] = {'@', '#', '$', '%'};
250 char test_buffer[sizeof(kOriginal)];
251 std::memcpy(test_buffer, kOriginal, sizeof(kOriginal));
252
Wyatt Hepler6d1a6c62020-06-22 15:40:45 -0700253 EXPECT_EQ(
254 0u,
255 ToString(std::string_view("Hello!"), std::span(test_buffer, 0)).size());
Wyatt Hepler58823c12019-11-13 14:27:31 -0800256 ASSERT_EQ(0, std::memcmp(kOriginal, test_buffer, sizeof(kOriginal)));
257}
258
259TEST(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