/Users/deen/code/yugabyte-db/src/yb/util/tostring-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright (c) YugaByte, Inc. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
5 | | // in compliance with the License. You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
10 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
11 | | // or implied. See the License for the specific language governing permissions and limitations |
12 | | // under the License. |
13 | | // |
14 | | // |
15 | | |
16 | | #include <deque> |
17 | | #include <list> |
18 | | #include <memory> |
19 | | #include <unordered_map> |
20 | | #include <vector> |
21 | | |
22 | | #include <boost/uuid/uuid_io.hpp> |
23 | | #include <gtest/gtest.h> |
24 | | |
25 | | #include "yb/gutil/ref_counted.h" |
26 | | #include "yb/gutil/strings/stringpiece.h" |
27 | | |
28 | | #include "yb/util/monotime.h" |
29 | | #include "yb/util/tostring.h" |
30 | | #include "yb/util/uuid.h" |
31 | | |
32 | | namespace yb { |
33 | | // We should use namespace other than yb::ToString to check how does ToString works |
34 | | // with code from other namespaces. |
35 | | namespace util_test { |
36 | | |
37 | | using yb::ToString; |
38 | | |
39 | | namespace { |
40 | | |
41 | | template<class T> |
42 | 18 | void CheckPlain(T t) { |
43 | 18 | ASSERT_EQ(std::to_string(t), ToString(t)); |
44 | 18 | } tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_110CheckPlainIiEEvT_ Line | Count | Source | 42 | 3 | void CheckPlain(T t) { | 43 | 3 | ASSERT_EQ(std::to_string(t), ToString(t)); | 44 | 3 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_110CheckPlainIsEEvT_ Line | Count | Source | 42 | 3 | void CheckPlain(T t) { | 43 | 3 | ASSERT_EQ(std::to_string(t), ToString(t)); | 44 | 3 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_110CheckPlainIjEEvT_ Line | Count | Source | 42 | 3 | void CheckPlain(T t) { | 43 | 3 | ASSERT_EQ(std::to_string(t), ToString(t)); | 44 | 3 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_110CheckPlainImEEvT_ Line | Count | Source | 42 | 3 | void CheckPlain(T t) { | 43 | 3 | ASSERT_EQ(std::to_string(t), ToString(t)); | 44 | 3 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_110CheckPlainIlEEvT_ Line | Count | Source | 42 | 3 | void CheckPlain(T t) { | 43 | 3 | ASSERT_EQ(std::to_string(t), ToString(t)); | 44 | 3 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_110CheckPlainIaEEvT_ Line | Count | Source | 42 | 3 | void CheckPlain(T t) { | 43 | 3 | ASSERT_EQ(std::to_string(t), ToString(t)); | 44 | 3 | } |
|
45 | | |
46 | | template<class T> |
47 | 6 | void CheckInt(T t) { |
48 | 6 | CheckPlain<T>(t); |
49 | 6 | CheckPlain<T>(std::numeric_limits<T>::min()); |
50 | 6 | CheckPlain<T>(std::numeric_limits<T>::max()); |
51 | 6 | } tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_18CheckIntIiEEvT_ Line | Count | Source | 47 | 1 | void CheckInt(T t) { | 48 | 1 | CheckPlain<T>(t); | 49 | 1 | CheckPlain<T>(std::numeric_limits<T>::min()); | 50 | 1 | CheckPlain<T>(std::numeric_limits<T>::max()); | 51 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_18CheckIntIsEEvT_ Line | Count | Source | 47 | 1 | void CheckInt(T t) { | 48 | 1 | CheckPlain<T>(t); | 49 | 1 | CheckPlain<T>(std::numeric_limits<T>::min()); | 50 | 1 | CheckPlain<T>(std::numeric_limits<T>::max()); | 51 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_18CheckIntIjEEvT_ Line | Count | Source | 47 | 1 | void CheckInt(T t) { | 48 | 1 | CheckPlain<T>(t); | 49 | 1 | CheckPlain<T>(std::numeric_limits<T>::min()); | 50 | 1 | CheckPlain<T>(std::numeric_limits<T>::max()); | 51 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_18CheckIntImEEvT_ Line | Count | Source | 47 | 1 | void CheckInt(T t) { | 48 | 1 | CheckPlain<T>(t); | 49 | 1 | CheckPlain<T>(std::numeric_limits<T>::min()); | 50 | 1 | CheckPlain<T>(std::numeric_limits<T>::max()); | 51 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_18CheckIntIlEEvT_ Line | Count | Source | 47 | 1 | void CheckInt(T t) { | 48 | 1 | CheckPlain<T>(t); | 49 | 1 | CheckPlain<T>(std::numeric_limits<T>::min()); | 50 | 1 | CheckPlain<T>(std::numeric_limits<T>::max()); | 51 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_18CheckIntIaEEvT_ Line | Count | Source | 47 | 1 | void CheckInt(T t) { | 48 | 1 | CheckPlain<T>(t); | 49 | 1 | CheckPlain<T>(std::numeric_limits<T>::min()); | 50 | 1 | CheckPlain<T>(std::numeric_limits<T>::max()); | 51 | 1 | } |
|
52 | | |
53 | | template<class T> |
54 | 9 | void CheckPointer(const std::string& tail, const T& t) { |
55 | 9 | if (t) { |
56 | 8 | std::stringstream ss; |
57 | 8 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) |
58 | 8 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; |
59 | 8 | ASSERT_EQ(ss.str(), ToString(t)); |
60 | 1 | } else { |
61 | 1 | ASSERT_EQ(tail, ToString(t)); |
62 | 1 | } |
63 | 9 | } tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerIPNSt3__16vectorIiNS3_9allocatorIiEEEEEEvRKNS3_12basic_stringIcNS3_11char_traitsIcEENS5_IcEEEERKT_ Line | Count | Source | 54 | 1 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 1 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 0 | } else { | 61 | 0 | ASSERT_EQ(tail, ToString(t)); | 62 | 0 | } | 63 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerIPNSt3__15dequeIiNS3_9allocatorIiEEEEEEvRKNS3_12basic_stringIcNS3_11char_traitsIcEENS5_IcEEEERKT_ Line | Count | Source | 54 | 1 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 1 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 0 | } else { | 61 | 0 | ASSERT_EQ(tail, ToString(t)); | 62 | 0 | } | 63 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerIPNSt3__14listIiNS3_9allocatorIiEEEEEEvRKNS3_12basic_stringIcNS3_11char_traitsIcEENS5_IcEEEERKT_ Line | Count | Source | 54 | 1 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 1 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 0 | } else { | 61 | 0 | ASSERT_EQ(tail, ToString(t)); | 62 | 0 | } | 63 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerIPiEEvRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEERKT_ Line | Count | Source | 54 | 2 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 2 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 1 | } else { | 61 | 1 | ASSERT_EQ(tail, ToString(t)); | 62 | 1 | } | 63 | 2 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerINSt3__110unique_ptrIiNS3_14default_deleteIiEEEEEEvRKNS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERKT_ Line | Count | Source | 54 | 1 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 1 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 0 | } else { | 61 | 0 | ASSERT_EQ(tail, ToString(t)); | 62 | 0 | } | 63 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerINSt3__110shared_ptrIiEEEEvRKNS3_12basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERKT_ Line | Count | Source | 54 | 1 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 1 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 0 | } else { | 61 | 0 | ASSERT_EQ(tail, ToString(t)); | 62 | 0 | } | 63 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerI13scoped_refptrINS0_12ToStringableEEEEvRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERKT_ Line | Count | Source | 54 | 1 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 1 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 0 | } else { | 61 | 0 | ASSERT_EQ(tail, ToString(t)); | 62 | 0 | } | 63 | 1 | } |
tostring-test.cc:_ZN2yb9util_test12_GLOBAL__N_112CheckPointerI13scoped_refptrINS0_17ToStringableChildEEEEvRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERKT_ Line | Count | Source | 54 | 1 | void CheckPointer(const std::string& tail, const T& t) { | 55 | 1 | if (t) { | 56 | 1 | std::stringstream ss; | 57 | 1 | ss << "0x" << std::setw(sizeof(void *) * 2) << std::setfill('0') << std::setbase(16) | 58 | 1 | << reinterpret_cast<size_t>(&*t) << " -> " << tail; | 59 | 1 | ASSERT_EQ(ss.str(), ToString(t)); | 60 | 0 | } else { | 61 | 0 | ASSERT_EQ(tail, ToString(t)); | 62 | 0 | } | 63 | 1 | } |
|
64 | | |
65 | | } // namespace |
66 | | |
67 | 1 | TEST(ToStringTest, TestNumber) { |
68 | 1 | CheckInt<int>(1984); |
69 | 1 | CheckInt<int16>(2349); |
70 | 1 | CheckInt<uint32_t>(23984296); |
71 | 1 | CheckInt<size_t>(2936429238477); |
72 | 1 | CheckInt<ptrdiff_t>(-962394729); |
73 | 1 | CheckInt<int8_t>(45); |
74 | 1 | ASSERT_EQ("1.23456789", ToString(1.234567890)); |
75 | 1 | ASSERT_EQ("1", ToString(1.0)); |
76 | 1 | ASSERT_EQ("1.5", ToString(1.5f)); |
77 | 1 | } |
78 | | |
79 | 1 | TEST(ToStringTest, TestCollection) { |
80 | 1 | const std::string expected = "[1, 2, 3, 4, 5]"; |
81 | 1 | std::vector<int> v = {1, 2, 3, 4, 5}; |
82 | 1 | ASSERT_EQ(expected, ToString(v)); |
83 | 1 | CheckPointer(expected, &v); |
84 | | |
85 | 1 | std::deque<int> d(v.begin(), v.end()); |
86 | 1 | ASSERT_EQ(expected, ToString(d)); |
87 | 1 | CheckPointer(expected, &d); |
88 | | |
89 | 1 | std::list<int> l(v.begin(), v.end()); |
90 | 1 | ASSERT_EQ(expected, ToString(l)); |
91 | 1 | CheckPointer(expected, &l); |
92 | | |
93 | 1 | auto pair = std::make_pair(v, d); |
94 | 1 | ASSERT_EQ("{" + expected + ", " + expected + "}", ToString(pair)); |
95 | 1 | } |
96 | | |
97 | 1 | TEST(ToStringTest, TestMap) { |
98 | 1 | std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}}; |
99 | 1 | ASSERT_EQ("[{1, one}, {2, two}, {3, three}]", ToString(m)); |
100 | | |
101 | 1 | std::unordered_map<int, std::string> u(m.begin(), m.end()); |
102 | 1 | auto uts = ToString(u); |
103 | 1 | std::vector<std::pair<int, std::string>> v(m.begin(), m.end()); |
104 | 1 | size_t match_count = 0; |
105 | 6 | for (;;) { |
106 | 6 | if (uts == ToString(v)) { |
107 | 1 | ++match_count; |
108 | 1 | } |
109 | 6 | if (!std::next_permutation(v.begin(), v.end())) { |
110 | 1 | break; |
111 | 1 | } |
112 | 6 | } |
113 | 1 | ASSERT_EQ(1, match_count); |
114 | 1 | } |
115 | | |
116 | 1 | TEST(ToStringTest, TestPointer) { |
117 | 1 | const char* some_text = "some text"; |
118 | | |
119 | 1 | ASSERT_EQ(some_text, ToString(some_text)); |
120 | 1 | int* null_int = nullptr; |
121 | 1 | CheckPointer("<NULL>", null_int); |
122 | | |
123 | 1 | std::string expected = "23"; |
124 | 1 | int number = 23; |
125 | 1 | CheckPointer(expected, &number); |
126 | | |
127 | 1 | std::unique_ptr<int> unique_ptr(new int(number)); |
128 | 1 | CheckPointer(expected, unique_ptr); |
129 | | |
130 | 1 | std::shared_ptr<int> shared_ptr = std::make_shared<int>(number); |
131 | 1 | CheckPointer(expected, shared_ptr); |
132 | 1 | } |
133 | | |
134 | | const std::string kShortDebugString = "ShortDebugString"; |
135 | | const std::string kToStringable = "ToStringable"; |
136 | | |
137 | | class ToStringable : public RefCountedThreadSafe<ToStringable> { |
138 | | public: |
139 | 5 | std::string ToString() const { |
140 | 5 | return kToStringable; |
141 | 5 | } |
142 | | }; |
143 | | |
144 | | class ToStringableChild : public ToStringable { |
145 | | }; |
146 | | |
147 | | class WithShortDebugString { |
148 | | public: |
149 | 2 | std::string ShortDebugString() const { |
150 | 2 | return kShortDebugString; |
151 | 2 | } |
152 | | }; |
153 | | |
154 | | class WithShortDebugStringChild : public WithShortDebugString { |
155 | | }; |
156 | | |
157 | 1 | TEST(ToStringTest, TestCustomIntrusive) { |
158 | 1 | scoped_refptr<ToStringable> ptr(new ToStringable); |
159 | 1 | scoped_refptr<ToStringableChild> child_ptr(new ToStringableChild); |
160 | 1 | ASSERT_EQ(kToStringable, ToString(*ptr)); |
161 | 1 | CheckPointer(kToStringable, ptr); |
162 | 1 | CheckPointer(kToStringable, child_ptr); |
163 | 1 | ASSERT_EQ(kShortDebugString, ToString(WithShortDebugString())); |
164 | 1 | ASSERT_EQ(kShortDebugString, ToString(WithShortDebugStringChild())); |
165 | | |
166 | 1 | std::vector<scoped_refptr<ToStringable>> v(2); |
167 | 1 | v[1] = ptr; |
168 | 1 | ASSERT_EQ("[<NULL>, " + ToString(v[1]) + "]", ToString(v)); |
169 | | |
170 | 1 | ASSERT_EQ(kToStringable, ToString(GStringPiece(kToStringable))); |
171 | 1 | } |
172 | | |
173 | | class ToStringableNonIntrusive { |
174 | | }; |
175 | | |
176 | 3 | std::string ToString(ToStringableNonIntrusive) { |
177 | 3 | return "ToStringableNonIntrusive"; |
178 | 3 | } |
179 | | |
180 | 1 | TEST(ToStringTest, TestCustomNonIntrusive) { |
181 | 1 | std::vector<ToStringableNonIntrusive> v(2); |
182 | 1 | ASSERT_EQ("ToStringableNonIntrusive", ToString(v[0])); |
183 | 1 | ASSERT_EQ("[ToStringableNonIntrusive, ToStringableNonIntrusive]", ToString(v)); |
184 | 1 | } |
185 | | |
186 | | struct Outputable { |
187 | | int value; |
188 | | |
189 | 2 | explicit Outputable(int v) : value(v) {} |
190 | | }; |
191 | | |
192 | 3 | std::ostream& operator<<(std::ostream& out, const Outputable& outputable) { |
193 | 3 | return out << "Outputable(" << outputable.value << ")"; |
194 | 3 | } |
195 | | |
196 | | class ToStringableAndOutputable { |
197 | | public: |
198 | 1 | std::string ToString() const { |
199 | 1 | return "ToString"; |
200 | 1 | } |
201 | | }; |
202 | | |
203 | 0 | std::ostream& operator<<(std::ostream& out, const ToStringableAndOutputable& outputable) { |
204 | 0 | return out << "operator<<"; |
205 | 0 | } |
206 | | |
207 | 1 | TEST(ToStringTest, LexicalCast) { |
208 | 1 | std::vector<Outputable> v = { Outputable(1), Outputable(2) }; |
209 | | |
210 | 1 | ASSERT_EQ("Outputable(1)", ToString(v[0])); |
211 | 1 | ASSERT_EQ("[Outputable(1), Outputable(2)]", ToString(v)); |
212 | 1 | ASSERT_EQ("ToString", ToString(ToStringableAndOutputable())); |
213 | 1 | ASSERT_EQ("0.000s", ToString(MonoDelta::kZero)); |
214 | 1 | } |
215 | | |
216 | 1 | TEST(ToStringTest, Uuid) { |
217 | 1 | const auto id = Uuid::Generate(); |
218 | 1 | auto str = to_string(id.impl()); |
219 | 1 | std::vector<boost::uuids::uuid> vec = {id.impl()}; |
220 | | |
221 | 1 | ASSERT_EQ(ToString(id), str); |
222 | 1 | ASSERT_EQ(ToString(vec), ToString(std::vector<std::string>{str})); |
223 | 1 | } |
224 | | |
225 | 1 | TEST(ToStringTest, Struct) { |
226 | 1 | struct TestStruct { |
227 | 1 | int a; |
228 | 1 | std::string b; |
229 | 1 | std::vector<int> c; |
230 | | |
231 | 1 | std::string ToString() const { |
232 | 1 | return YB_STRUCT_TO_STRING(a, b, c); |
233 | 1 | } |
234 | 1 | }; |
235 | | |
236 | 1 | TestStruct t = { |
237 | 1 | .a = 42, |
238 | 1 | .b = "test", |
239 | 1 | .c = {1, 2, 3}, |
240 | 1 | }; |
241 | | |
242 | 1 | ASSERT_EQ(t.ToString(), "{ a: 42 b: test c: [1, 2, 3] }"); |
243 | | |
244 | 1 | class TestClass { |
245 | 1 | public: |
246 | 1 | TestClass(int a, std::string b) : a_(a), b_(std::move(b)) {} |
247 | | |
248 | 1 | std::string ToString() const { |
249 | 1 | return YB_CLASS_TO_STRING(a, b); |
250 | 1 | } |
251 | | |
252 | 1 | private: |
253 | 1 | int a_; |
254 | 1 | std::string b_; |
255 | 1 | }; |
256 | | |
257 | 1 | ASSERT_EQ(TestClass(42, "test").ToString(), "{ a: 42 b: test }"); |
258 | 1 | } |
259 | | |
260 | | } // namespace util_test |
261 | | } // namespace yb |