/Users/deen/code/yugabyte-db/src/yb/util/test_macros.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | #ifndef YB_UTIL_TEST_MACROS_H |
33 | | #define YB_UTIL_TEST_MACROS_H |
34 | | |
35 | | #include <set> |
36 | | #include <sstream> |
37 | | #include <string> |
38 | | |
39 | | #include <boost/preprocessor/cat.hpp> |
40 | | |
41 | | #include <gtest/gtest.h> // For SUCCEED/FAIL |
42 | | |
43 | | #include "yb/util/tostring.h" |
44 | | #include "yb/gutil/stl_util.h" // For VectorToSet |
45 | | |
46 | | namespace yb { |
47 | | namespace util { |
48 | | |
49 | | template<typename T> |
50 | | std::string TEST_SetDifferenceStr(const std::set<T>& expected, const std::set<T>& actual) { |
51 | | std::set<T> only_in_expected, only_in_actual; |
52 | | for (const auto& expected_item : expected) { |
53 | | if (!actual.count(expected_item)) { |
54 | | only_in_expected.insert(expected_item); |
55 | | } |
56 | | } |
57 | | |
58 | | for (const auto& actual_item : actual) { |
59 | | if (!expected.count(actual_item)) { |
60 | | only_in_actual.insert(actual_item); |
61 | | } |
62 | | } |
63 | | |
64 | | std::ostringstream result; |
65 | | if (!only_in_expected.empty()) { |
66 | | result << "only in the expected set: " << yb::ToString(only_in_expected); |
67 | | } |
68 | | if (!only_in_actual.empty()) { |
69 | | if (result.tellp() > 0) { |
70 | | result << "; "; |
71 | | } |
72 | | result << "only in the actual set: " << yb::ToString(only_in_actual); |
73 | | } |
74 | | if (result.tellp() == 0) { |
75 | | return "no differences"; |
76 | | } |
77 | | return result.str(); |
78 | | } |
79 | | |
80 | | } // namespace util |
81 | | } // namespace yb |
82 | | |
83 | | // ASSERT_NO_FATAL_FAILURE is just too long to type. |
84 | | #define NO_FATALS(expr) \ |
85 | | ASSERT_NO_FATAL_FAILURE(expr) |
86 | | |
87 | | // Detect fatals in the surrounding scope. NO_FATALS() only checks for fatals |
88 | | // in the expression passed to it. |
89 | | #define NO_PENDING_FATALS() \ |
90 | | if (testing::Test::HasFatalFailure()) { return; } |
91 | | |
92 | | // ASSERT_NO_FATAL_FAILURE is just too long to type. |
93 | 5.42k | #define ASSERT_NO_FATALS ASSERT_NO_FATAL_FAILURE |
94 | | |
95 | | // We are using "const auto" for storing the status so that the same macros work for both YB and |
96 | | // RocksDB's Status types. |
97 | | |
98 | 796k | #define ASSERT_OK(status) do { \ |
99 | 796k | auto&& _assert_status = (status122k ); \ remote_bootstrap_session-test.cc:yb::tserver::RemoteBootstrapSessionTest::SetUpTabletPeer()::$_0::operator()() const Line | Count | Source | 99 | 28 | auto&& _assert_status = (status); \ |
Unexecuted instantiation: cdc_test_util.cc:yb::cdc::WaitUntilWalRetentionSecs(std::__1::function<int ()>, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0::operator()() const yb_table_test_base.cc:yb::integration_tests::YBTableTestBase::WaitForLoadBalanceCompletion(yb::MonoDelta)::$_0::operator()() const Line | Count | Source | 99 | 1.29k | auto&& _assert_status = (status); \ |
yb_table_test_base.cc:yb::integration_tests::YBTableTestBase::WaitForLoadBalanceCompletion(yb::MonoDelta)::$_1::operator()() const Line | Count | Source | 99 | 1.07k | auto&& _assert_status = (status); \ |
|
100 | 796k | if (_assert_status.ok()) { \ |
101 | 796k | SUCCEED(); \ |
102 | 796k | } else { \ |
103 | 747 | FAIL() << "Bad status: " << StatusToString(_assert_status); \ |
104 | 747 | } \ |
105 | 796k | } while (0796k ) |
106 | | |
107 | | #define ASSERT_NOK(s) ASSERT_FALSE((s).ok()) |
108 | | |
109 | | #define ASSERT_OK_PREPEND(status, msg) do { \ |
110 | | auto&& _assert_status = (status); \ |
111 | | if (_assert_status.ok()) { \ |
112 | | SUCCEED(); \ |
113 | | } else { \ |
114 | | FAIL() << (msg) << " - status: " << StatusToString(_assert_status); \ |
115 | | } \ |
116 | | } while (0) |
117 | | |
118 | | #ifdef EXPECT_OK |
119 | | #undef EXPECT_OK |
120 | | #endif |
121 | | |
122 | 870 | #define EXPECT_OK(status) do { \ |
123 | 870 | auto&& _s = (status); \ |
124 | 870 | if (_s.ok()) { \ |
125 | 870 | SUCCEED(); \ |
126 | 870 | } else { \ |
127 | 0 | ADD_FAILURE() << "Bad status: " << StatusToString(_s); \ |
128 | 0 | } \ |
129 | 870 | } while (0) |
130 | | |
131 | | #define EXPECT_NOT_OK(s) EXPECT_FALSE((s).ok()) |
132 | | |
133 | | // Like the above, but doesn't record successful |
134 | | // tests. |
135 | 5.14k | #define ASSERT_OK_FAST(status) do { \ |
136 | 5.14k | auto&& _assert_status = (status); \ |
137 | 5.14k | if (!_assert_status.ok()) { \ |
138 | 0 | FAIL() << "Bad status: " << StatusToString(_assert_status); \ |
139 | 0 | } \ |
140 | 5.14k | } while (0) |
141 | | |
142 | | #define ASSERT_NO_ERROR(ec) \ |
143 | | do { \ |
144 | | auto&& _ec = (ec); \ |
145 | | if (!_ec) { \ |
146 | | SUCCEED(); \ |
147 | | } else { \ |
148 | | FAIL() << "Unexpected error: " << ec.message(); \ |
149 | | } \ |
150 | | } while (false) |
151 | | |
152 | | #define EXPECT_NO_ERROR(ec) \ |
153 | | do { \ |
154 | | auto&& _ec = (ec); \ |
155 | | if (!_ec) { \ |
156 | | SUCCEED(); \ |
157 | | } else { \ |
158 | | ADD_FAILURE() << "Unexpected error: " << ec.message(); \ |
159 | | } \ |
160 | | } while (false) |
161 | | |
162 | | #ifdef THREAD_SANITIZER |
163 | | #define ASSERT_PERF_LE(lhs, rhs) do { (void)(lhs); (void)(rhs); } while(false) |
164 | | #define EXPECT_PERF_LE(lhs, rhs) do { (void)(lhs); (void)(rhs); } while(false) |
165 | | #else |
166 | | #define ASSERT_PERF_LE(lhs, rhs) ASSERT_LE(lhs, rhs) |
167 | | #define EXPECT_PERF_LE(lhs, rhs) EXPECT_LE(lhs, rhs) |
168 | | #endif |
169 | | |
170 | | #define ASSERT_STR_CONTAINS(str, substr) do { \ |
171 | | std::string _s = (str); \ |
172 | | if (_s.find((substr)) == std::string::npos) { \ |
173 | | FAIL() << "Expected to find substring '" << (substr) \ |
174 | | << "'. Got: '" << _s << "'"; \ |
175 | | } \ |
176 | | } while (0) |
177 | | |
178 | | #define ASSERT_STR_NOT_CONTAINS(str, substr) do { \ |
179 | | std::string _s = (str); \ |
180 | | if (_s.find((substr)) != std::string::npos) { \ |
181 | | FAIL() << "Expected not to find substring '" << (substr) \ |
182 | | << "'. Got: '" << _s << "'"; \ |
183 | | } \ |
184 | | } while (0) |
185 | | |
186 | 0 | inline std::string FindFirstDiff(const std::string& lhs, const std::string& rhs) { |
187 | 0 | size_t min_len = std::min(lhs.size(), rhs.size()); |
188 | 0 | size_t i = 0; |
189 | 0 | for (; i != min_len; ++i) { |
190 | 0 | if (lhs[i] != rhs[i]) { |
191 | 0 | break; |
192 | 0 | } |
193 | 0 | } |
194 | 0 | return lhs.substr(i, std::min<size_t>(lhs.size() - i, 32)) + " vs " + |
195 | 0 | rhs.substr(i, std::min<size_t>(rhs.size() - i, 32)); |
196 | 0 | } |
197 | | |
198 | 1 | #define ASSERT_STR_EQ(lhs, rhs) do { \ |
199 | 1 | std::string _lhs = (lhs); \ |
200 | 1 | std::string _rhs = (rhs); \ |
201 | 2 | ASSERT_EQ(lhs, rhs) << "First diff: " << FindFirstDiff(lhs, rhs); \ |
202 | 1 | } while (0) |
203 | | |
204 | | #define ASSERT_FILE_EXISTS(env, path) do { \ |
205 | | std::string _s = (path); \ |
206 | | ASSERT_TRUE(env->FileExists(_s)) \ |
207 | | << "Expected file to exist: " << _s; \ |
208 | | } while (0) |
209 | | |
210 | | #define ASSERT_FILE_NOT_EXISTS(env, path) do { \ |
211 | | std::string _s = (path); \ |
212 | | ASSERT_FALSE(env->FileExists(_s)) \ |
213 | | << "Expected file not to exist: " << _s; \ |
214 | | } while (0) |
215 | | |
216 | | // Wrappers around ASSERT_EQ and EXPECT_EQ that trim expected and actual strings and outputs |
217 | | // expected and actual values without any escaping. We're also printing a stack trace to allow |
218 | | // easier debugging. |
219 | | #define _ASSERT_EXPECT_STR_EQ_VERBOSE_COMMON_SETUP(expected, actual) \ |
220 | 207k | const auto expected_tmp = ::yb::util::TrimStr(yb::util::LeftShiftTextBlock(expected)); \ |
221 | 207k | const auto actual_tmp = ::yb::util::TrimStr(yb::util::LeftShiftTextBlock(actual)); |
222 | | |
223 | | #define _ASSERT_EXPECT_STR_EQ_VERBOSE_COMMON_MSG \ |
224 | 0 | "\nActual (trimmed):\n" << actual_tmp \ |
225 | 0 | << "\n\nExpected (trimmed):\n" << expected_tmp; |
226 | | |
227 | | #define ASSERT_STR_EQ_VERBOSE_TRIMMED(expected, actual) \ |
228 | 207k | do { \ |
229 | 207k | _ASSERT_EXPECT_STR_EQ_VERBOSE_COMMON_SETUP(expected, actual) \ |
230 | 414k | ASSERT_EQ(expected_tmp, actual_tmp) << _ASSERT_EXPECT_STR_EQ_VERBOSE_COMMON_MSG0 ; \ |
231 | 207k | } while(0) |
232 | | |
233 | | #define ASSERT_SETS_EQ(expected_set, actual_set) \ |
234 | | do { \ |
235 | | auto&& expected_set_computed = (expected_set); \ |
236 | | auto&& actual_set_computed = (actual_set); \ |
237 | | if (expected_set_computed != actual_set_computed) { \ |
238 | | FAIL() << "Expected " \ |
239 | | << BOOST_PP_STRINGIZE(actual_set) << " to be equal to " \ |
240 | | << BOOST_PP_STRINGIZE(expected_set) << ". Differences: " \ |
241 | | << ::yb::util::TEST_SetDifferenceStr(expected_set_computed, actual_set_computed); \ |
242 | | } \ |
243 | | } while (0) |
244 | | |
245 | | // Compare vectors of "comparable" values that can be put inside an std::set. Because they are |
246 | | // comparable, we also show the differences between the set of elements in vectors, which is |
247 | | // sometimes the only way to see what is different. |
248 | | // |
249 | | // Using a simple name ASSERT_VECTORS_EQ for this macro rather than a more verbose and precise but |
250 | | // more confusing such as ASSERT_VECTORS_OF_COMPARABLE_EQ. |
251 | | // |
252 | | // Google Test says "do not use this in your code" about GTEST_PRED_FORMAT2_, but we need to use it |
253 | | // to correctly propagate the raw text of expressions to the error message. We pass the string |
254 | | // representation of the actual macro parameters but the ..._computed values as values (to avoid |
255 | | // multiple evaluations). |
256 | | // |
257 | | // Here are macros from gtest that were used to construct the implementation below: |
258 | | // |
259 | | // ASSERT_EQ -> GTEST_ASSERT_EQ -> ASSERT_PRED_FORMAT2 -> GTEST_PRED_FORMAT2_ -> GTEST_ASSERT_ |
260 | | #define ASSERT_VECTORS_EQ(expected_vector, actual_vector) \ |
261 | | do { \ |
262 | | auto&& expected_vector_computed = (expected_vector); \ |
263 | | auto&& actual_vector_computed = (actual_vector); \ |
264 | | auto expected_set = ::yb::VectorToSet(expected_vector_computed); \ |
265 | | auto actual_set = ::yb::VectorToSet(actual_vector_computed); \ |
266 | | GTEST_ASSERT_( \ |
267 | | ::testing::internal::EqHelper<GTEST_IS_NULL_LITERAL_(expected_vector)>::Compare( \ |
268 | | BOOST_PP_STRINGIZE(expected_vector), \ |
269 | | BOOST_PP_STRINGIZE(actual_vector), \ |
270 | | expected_vector_computed, \ |
271 | | actual_vector_computed), \ |
272 | | GTEST_FATAL_FAILURE_) \ |
273 | | << "Differences (as sets): " \ |
274 | | << ::yb::util::TEST_SetDifferenceStr(expected_set, actual_set); \ |
275 | | } while (0) |
276 | | |
277 | | // A wrapper around EXPECT_EQ that trims expected and actual strings and outputs expected and actual |
278 | | // values without any escaping. |
279 | | #define EXPECT_STR_EQ_VERBOSE_TRIMMED(expected, actual) \ |
280 | | do { \ |
281 | | _ASSERT_EXPECT_STR_EQ_VERBOSE_COMMON_SETUP(expected, actual) \ |
282 | | EXPECT_EQ(expected_tmp, actual_tmp) << _ASSERT_EXPECT_STR_EQ_VERBOSE_COMMON_MSG; \ |
283 | | } while(0) |
284 | | |
285 | | #define YB_ASSERT_TRUE(condition) \ |
286 | | GTEST_TEST_BOOLEAN_((condition) ? true : false, #condition, false, true, \ |
287 | | GTEST_FATAL_FAILURE_) |
288 | | |
289 | | #define VERIFY_EQ(expected_expr, actual_expr) \ |
290 | | do { \ |
291 | | auto&& expected = (expected_expr); \ |
292 | | auto&& actual = (actual_expr); \ |
293 | | if (expected != actual) { \ |
294 | | return ::testing::internal::EqFailure( \ |
295 | | BOOST_PP_STRINGIZE(expected_expr), \ |
296 | | BOOST_PP_STRINGIZE(actual_expr), \ |
297 | | ::testing::internal::FormatForComparisonFailureMessage(expected, actual), \ |
298 | | ::testing::internal::FormatForComparisonFailureMessage(actual, expected), \ |
299 | | false); \ |
300 | | } \ |
301 | | } while (false) \ |
302 | | /**/ |
303 | | |
304 | | #define ASSERT_VERIFY(expr) \ |
305 | | do { \ |
306 | | auto&& result = (expr); \ |
307 | | if (!result) { \ |
308 | | FAIL() << result.message(); \ |
309 | | } \ |
310 | | } while (false) \ |
311 | | /**/ |
312 | | |
313 | | // Asserts that expr is not null, returns expr in case of success. |
314 | | #define ASSERT_NOTNULL(expr) \ |
315 | | __extension__ ({ \ |
316 | | auto&& result = (expr); \ |
317 | | if (result == nullptr) { \ |
318 | | FAIL() << "Unexpected nullptr"; \ |
319 | | } \ |
320 | | std::move(result); \ |
321 | | }) \ |
322 | | /**/ |
323 | | |
324 | | #define CURRENT_TEST_NAME() \ |
325 | 12 | ::testing::UnitTest::GetInstance()->current_test_info()->name() |
326 | | |
327 | | #define CURRENT_TEST_CASE_NAME() \ |
328 | 0 | ::testing::UnitTest::GetInstance()->current_test_info()->test_case_name() |
329 | | |
330 | | #define CURRENT_TEST_CASE_AND_TEST_NAME_STR() \ |
331 | | (std::string(CURRENT_TEST_CASE_NAME()) + '.' + CURRENT_TEST_NAME()) |
332 | | |
333 | | #define YB_DISABLE_TEST(test_name) BOOST_PP_CAT(DISABLED_, test_name) |
334 | | |
335 | | #ifdef __APPLE__ |
336 | | #define YB_DISABLE_TEST_ON_MACOS(test_name) YB_DISABLE_TEST(test_name) |
337 | | #else |
338 | | #define YB_DISABLE_TEST_ON_MACOS(test_name) test_name |
339 | | #endif |
340 | | |
341 | | #ifdef THREAD_SANITIZER |
342 | | #define YB_DISABLE_TEST_IN_TSAN(test_name) YB_DISABLE_TEST(test_name) |
343 | | #else |
344 | | #define YB_DISABLE_TEST_IN_TSAN(test_name) test_name |
345 | | #endif |
346 | | |
347 | | #if defined(THREAD_SANITIZER) || defined(ADDRESS_SANITIZER) |
348 | | #define YB_DISABLE_TEST_IN_SANITIZERS(test_name) YB_DISABLE_TEST(test_name) |
349 | | #else |
350 | | #define YB_DISABLE_TEST_IN_SANITIZERS(test_name) test_name |
351 | | #endif |
352 | | |
353 | | #if defined(__APPLE__) || defined(THREAD_SANITIZER) || defined(ADDRESS_SANITIZER) |
354 | | #define YB_DISABLE_TEST_IN_SANITIZERS_OR_MAC(test_name) YB_DISABLE_TEST(test_name) |
355 | | #else |
356 | | #define YB_DISABLE_TEST_IN_SANITIZERS_OR_MAC(test_name) test_name |
357 | | #endif |
358 | | |
359 | | // TODO: use GTEST_SKIP() here when we upgrade gtest. |
360 | | #define YB_SKIP_TEST_IN_TSAN() do { \ |
361 | | if (::yb::IsTsan()) { \ |
362 | | LOG(INFO) << "This test is skipped in TSAN"; \ |
363 | | return; \ |
364 | | } \ |
365 | | } while (false) |
366 | | |
367 | | #endif // YB_UTIL_TEST_MACROS_H |