1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <tuple>
6
7 #include "base/check_deref.h"
8 #include "base/check_version_internal.h"
9 #include "base/dcheck_is_on.h"
10 #include "base/debug/dump_without_crashing.h"
11 #include "base/features.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/logging.h"
15 #include "base/macros/concat.h"
16 #include "base/notimplemented.h"
17 #include "base/notreached.h"
18 #include "base/strings/string_piece.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/test/gtest_util.h"
21 #include "base/test/scoped_feature_list.h"
22 #include "build/build_config.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace {
27
28 int g_dump_without_crashing_count = 0;
29
30 constexpr base::NotFatalUntil kNextMilestone =
31 BASE_CONCAT(base::NotFatalUntil::M, BASE_CHECK_NEXT_VERSION_INTERNAL);
32 constexpr base::NotFatalUntil kCurrentMilestone =
33 BASE_CONCAT(base::NotFatalUntil::M, BASE_CHECK_VERSION_INTERNAL);
34
35 class ScopedExpectDumpWithoutCrashing {
36 public:
ScopedExpectDumpWithoutCrashing()37 ScopedExpectDumpWithoutCrashing() {
38 g_dump_without_crashing_count = 0;
39 base::debug::SetDumpWithoutCrashingFunction(&DumpWithoutCrashing);
40 }
41
~ScopedExpectDumpWithoutCrashing()42 ~ScopedExpectDumpWithoutCrashing() {
43 EXPECT_EQ(1, g_dump_without_crashing_count);
44 base::debug::SetDumpWithoutCrashingFunction(nullptr);
45 }
46
47 private:
DumpWithoutCrashing()48 static void DumpWithoutCrashing() { ++g_dump_without_crashing_count; }
49 };
50
51 MATCHER_P2(LogErrorMatches, line, expected_msg, "") {
52 EXPECT_THAT(arg, testing::HasSubstr(
53 base::StringPrintf("check_unittest.cc(%d)] ", line)));
54 if (std::string(expected_msg).find("=~") == 0) {
55 EXPECT_THAT(std::string(arg),
56 testing::ContainsRegex(std::string(expected_msg).substr(2)));
57 } else {
58 EXPECT_THAT(std::string(arg), testing::HasSubstr(expected_msg));
59 }
60 return true;
61 }
62
63 // TODO(pbos): Upstream support for ignoring matchers in gtest when death
64 // testing is not available.
65 // Without this we get a compile failure on iOS because
66 // GTEST_UNSUPPORTED_DEATH_TEST does not compile with a MATCHER as parameter.
67 #if GTEST_HAS_DEATH_TEST
68 #define CHECK_MATCHER(line, msg) LogErrorMatches(line, msg)
69 #else
70 #define CHECK_MATCHER(line, msg) msg
71 #endif
72
73 // Macro which expects a CHECK to fire with a certain message. If msg starts
74 // with "=~", it's interpreted as a regular expression.
75 // Example: EXPECT_CHECK("Check failed: false.", CHECK(false));
76 //
77 // Note: Please use the `CheckDeathTest` fixture when using this check.
78 #if !CHECK_WILL_STREAM()
79 #define EXPECT_CHECK(msg, check_expr) \
80 do { \
81 EXPECT_CHECK_DEATH(check_expr); \
82 } while (0)
83 #else
84 #define EXPECT_CHECK(msg, check_expr) \
85 EXPECT_DEATH_IF_SUPPORTED(check_expr, CHECK_MATCHER(__LINE__, msg))
86 #endif // !CHECK_WILL_STREAM()
87
88 // Macro which expects a DCHECK to fire if DCHECKs are enabled.
89 //
90 // Note: Please use the `CheckDeathTest` fixture when using this check.
91 #define EXPECT_DCHECK(msg, check_expr) \
92 do { \
93 if (DCHECK_IS_ON() && logging::LOGGING_DCHECK == logging::LOGGING_FATAL) { \
94 EXPECT_DEATH_IF_SUPPORTED(check_expr, CHECK_MATCHER(__LINE__, msg)); \
95 } else if (DCHECK_IS_ON()) { \
96 ScopedExpectDumpWithoutCrashing expect_dump; \
97 check_expr; \
98 } else { \
99 check_expr; \
100 } \
101 } while (0)
102
103 #define EXPECT_LOG_ERROR_WITH_FILENAME(expected_file, expected_line, expr, \
104 msg) \
105 do { \
106 static bool got_log_message = false; \
107 ASSERT_EQ(logging::GetLogMessageHandler(), nullptr); \
108 logging::SetLogMessageHandler([](int severity, const char* file, int line, \
109 size_t message_start, \
110 const std::string& str) { \
111 EXPECT_FALSE(got_log_message); \
112 got_log_message = true; \
113 EXPECT_EQ(severity, logging::LOGGING_ERROR); \
114 EXPECT_EQ(str.substr(message_start), (msg)); \
115 if (base::StringPiece(expected_file) != "") { \
116 EXPECT_STREQ(expected_file, file); \
117 } \
118 if (expected_line != -1) { \
119 EXPECT_EQ(expected_line, line); \
120 } \
121 return true; \
122 }); \
123 expr; \
124 EXPECT_TRUE(got_log_message); \
125 logging::SetLogMessageHandler(nullptr); \
126 } while (0)
127
128 #define EXPECT_LOG_ERROR(expected_line, expr, msg) \
129 EXPECT_LOG_ERROR_WITH_FILENAME(__FILE__, expected_line, expr, msg)
130
131 #define EXPECT_NO_LOG(expr) \
132 do { \
133 ASSERT_EQ(logging::GetLogMessageHandler(), nullptr); \
134 logging::SetLogMessageHandler([](int severity, const char* file, int line, \
135 size_t message_start, \
136 const std::string& str) { \
137 EXPECT_TRUE(false) << "Unexpected log: " << str; \
138 return true; \
139 }); \
140 expr; \
141 logging::SetLogMessageHandler(nullptr); \
142 } while (0)
143
144 #if DCHECK_IS_ON()
145 #define EXPECT_DUMP_WILL_BE_CHECK EXPECT_DCHECK
146 #else
147 #define EXPECT_DUMP_WILL_BE_CHECK(expected_string, statement) \
148 do { \
149 ScopedExpectDumpWithoutCrashing expect_dump; \
150 EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(), \
151 base::Location::Current().line_number(), \
152 statement, expected_string "\n"); \
153 } while (0)
154 #endif // DCHECK_IS_ON()
155
TEST(CheckDeathTest,Basics)156 TEST(CheckDeathTest, Basics) {
157 EXPECT_CHECK("Check failed: false. ", CHECK(false));
158
159 EXPECT_CHECK("Check failed: false. foo", CHECK(false) << "foo");
160
161 double a = 2, b = 1;
162 EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)", CHECK_LT(a, b));
163
164 EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)custom message",
165 CHECK_LT(a, b) << "custom message");
166 }
167
TEST(CheckDeathTest,PCheck)168 TEST(CheckDeathTest, PCheck) {
169 const char file[] = "/nonexistentfile123";
170 std::ignore = fopen(file, "r");
171 std::string err =
172 logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
173
174 EXPECT_CHECK(
175 "Check failed: fopen(file, \"r\") != nullptr."
176 " : " +
177 err,
178 PCHECK(fopen(file, "r") != nullptr));
179
180 EXPECT_CHECK(
181 "Check failed: fopen(file, \"r\") != nullptr."
182 " foo: " +
183 err,
184 PCHECK(fopen(file, "r") != nullptr) << "foo");
185
186 EXPECT_DCHECK(
187 "Check failed: fopen(file, \"r\") != nullptr."
188 " : " +
189 err,
190 DPCHECK(fopen(file, "r") != nullptr));
191
192 EXPECT_DCHECK(
193 "Check failed: fopen(file, \"r\") != nullptr."
194 " foo: " +
195 err,
196 DPCHECK(fopen(file, "r") != nullptr) << "foo");
197 }
198
TEST(CheckDeathTest,CheckOp)199 TEST(CheckDeathTest, CheckOp) {
200 const int a = 1, b = 2;
201 // clang-format off
202 EXPECT_CHECK("Check failed: a == b (1 vs. 2)", CHECK_EQ(a, b));
203 EXPECT_CHECK("Check failed: a != a (1 vs. 1)", CHECK_NE(a, a));
204 EXPECT_CHECK("Check failed: b <= a (2 vs. 1)", CHECK_LE(b, a));
205 EXPECT_CHECK("Check failed: b < a (2 vs. 1)", CHECK_LT(b, a));
206 EXPECT_CHECK("Check failed: a >= b (1 vs. 2)", CHECK_GE(a, b));
207 EXPECT_CHECK("Check failed: a > b (1 vs. 2)", CHECK_GT(a, b));
208
209 EXPECT_DCHECK("Check failed: a == b (1 vs. 2)", DCHECK_EQ(a, b));
210 EXPECT_DCHECK("Check failed: a != a (1 vs. 1)", DCHECK_NE(a, a));
211 EXPECT_DCHECK("Check failed: b <= a (2 vs. 1)", DCHECK_LE(b, a));
212 EXPECT_DCHECK("Check failed: b < a (2 vs. 1)", DCHECK_LT(b, a));
213 EXPECT_DCHECK("Check failed: a >= b (1 vs. 2)", DCHECK_GE(a, b));
214 EXPECT_DCHECK("Check failed: a > b (1 vs. 2)", DCHECK_GT(a, b));
215 // clang-format on
216
217 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a == b (1 vs. 2)",
218 DUMP_WILL_BE_CHECK_EQ(a, b));
219 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a != a (1 vs. 1)",
220 DUMP_WILL_BE_CHECK_NE(a, a));
221 EXPECT_DUMP_WILL_BE_CHECK("Check failed: b <= a (2 vs. 1)",
222 DUMP_WILL_BE_CHECK_LE(b, a));
223 EXPECT_DUMP_WILL_BE_CHECK("Check failed: b < a (2 vs. 1)",
224 DUMP_WILL_BE_CHECK_LT(b, a));
225 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a >= b (1 vs. 2)",
226 DUMP_WILL_BE_CHECK_GE(a, b));
227 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a > b (1 vs. 2)",
228 DUMP_WILL_BE_CHECK_GT(a, b));
229 }
230
TEST(CheckTest,CheckStreamsAreLazy)231 TEST(CheckTest, CheckStreamsAreLazy) {
232 int called_count = 0;
233 int not_called_count = 0;
234
235 auto Called = [&]() {
236 ++called_count;
237 // This returns a non-constant because returning 42 here directly triggers a
238 // dead-code warning when streaming to *CHECK(Called()) << NotCalled();
239 return called_count >= 0;
240 };
241 auto NotCalled = [&]() {
242 ++not_called_count;
243 return 42;
244 };
245
246 CHECK(Called()) << NotCalled();
247 CHECK_EQ(Called(), Called()) << NotCalled();
248 PCHECK(Called()) << NotCalled();
249
250 DCHECK(Called()) << NotCalled();
251 DCHECK_EQ(Called(), Called()) << NotCalled();
252 DPCHECK(Called()) << NotCalled();
253
254 EXPECT_EQ(not_called_count, 0);
255 #if DCHECK_IS_ON()
256 EXPECT_EQ(called_count, 8);
257 #else
258 EXPECT_EQ(called_count, 4);
259 #endif
260 }
261
DcheckEmptyFunction1()262 void DcheckEmptyFunction1() {
263 // Provide a body so that Release builds do not cause the compiler to
264 // optimize DcheckEmptyFunction1 and DcheckEmptyFunction2 as a single
265 // function, which breaks the Dcheck tests below.
266 LOG(INFO) << "DcheckEmptyFunction1";
267 }
DcheckEmptyFunction2()268 void DcheckEmptyFunction2() {}
269
270 #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
271 class ScopedDcheckSeverity {
272 public:
ScopedDcheckSeverity(logging::LogSeverity new_severity)273 explicit ScopedDcheckSeverity(logging::LogSeverity new_severity)
274 : old_severity_(logging::LOGGING_DCHECK) {
275 logging::LOGGING_DCHECK = new_severity;
276 }
277
~ScopedDcheckSeverity()278 ~ScopedDcheckSeverity() { logging::LOGGING_DCHECK = old_severity_; }
279
280 private:
281 logging::LogSeverity old_severity_;
282 };
283 #endif // BUILDFLAG(DCHECK_IS_CONFIGURABLE)
284
TEST(CheckDeathTest,Dcheck)285 TEST(CheckDeathTest, Dcheck) {
286 #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
287 // DCHECKs are enabled, and LOGGING_DCHECK is mutable, but defaults to
288 // non-fatal. Set it to LOGGING_FATAL to get the expected behavior from the
289 // rest of this test.
290 ScopedDcheckSeverity dcheck_severity(logging::LOGGING_FATAL);
291 #endif // BUILDFLAG(DCHECK_IS_CONFIGURABLE)
292
293 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
294 // Release build.
295 EXPECT_FALSE(DCHECK_IS_ON());
296 #elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
297 // Release build with real DCHECKS.
298 EXPECT_TRUE(DCHECK_IS_ON());
299 #else
300 // Debug build.
301 EXPECT_TRUE(DCHECK_IS_ON());
302 #endif
303
304 EXPECT_DCHECK("Check failed: false. ", DCHECK(false));
305
306 // Produce a consistent error code so that both the main instance of this test
307 // and the EXPECT_DEATH invocation below get the same error codes for DPCHECK.
308 const char file[] = "/nonexistentfile123";
309 std::ignore = fopen(file, "r");
310 std::string err =
311 logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
312 EXPECT_DCHECK("Check failed: false. : " + err, DPCHECK(false));
313 EXPECT_DCHECK("Check failed: 0 == 1 (0 vs. 1)", DCHECK_EQ(0, 1));
314
315 // Test DCHECK on std::nullptr_t
316 const void* p_null = nullptr;
317 const void* p_not_null = &p_null;
318 DCHECK_EQ(p_null, nullptr);
319 DCHECK_EQ(nullptr, p_null);
320 DCHECK_NE(p_not_null, nullptr);
321 DCHECK_NE(nullptr, p_not_null);
322
323 // Test DCHECK on a scoped enum.
324 enum class Animal { DOG, CAT };
325 DCHECK_EQ(Animal::DOG, Animal::DOG);
326 EXPECT_DCHECK("Check failed: Animal::DOG == Animal::CAT (0 vs. 1)",
327 DCHECK_EQ(Animal::DOG, Animal::CAT));
328
329 // Test DCHECK on functions and function pointers.
330 struct MemberFunctions {
331 void MemberFunction1() {
332 // See the comment in DcheckEmptyFunction1().
333 LOG(INFO) << "Do not merge with MemberFunction2.";
334 }
335 void MemberFunction2() {}
336 };
337 void (MemberFunctions::*mp1)() = &MemberFunctions::MemberFunction1;
338 void (MemberFunctions::*mp2)() = &MemberFunctions::MemberFunction2;
339 void (*fp1)() = DcheckEmptyFunction1;
340 void (*fp2)() = DcheckEmptyFunction2;
341 void (*fp3)() = DcheckEmptyFunction1;
342 DCHECK_EQ(fp1, fp3);
343 DCHECK_EQ(mp1, &MemberFunctions::MemberFunction1);
344 DCHECK_EQ(mp2, &MemberFunctions::MemberFunction2);
345 EXPECT_DCHECK("=~Check failed: fp1 == fp2 \\(\\w+ vs. \\w+\\)",
346 DCHECK_EQ(fp1, fp2));
347 EXPECT_DCHECK(
348 "Check failed: mp2 == &MemberFunctions::MemberFunction1 (1 vs. 1)",
349 DCHECK_EQ(mp2, &MemberFunctions::MemberFunction1));
350 }
351
TEST(CheckTest,DcheckReleaseBehavior)352 TEST(CheckTest, DcheckReleaseBehavior) {
353 int var1 = 1;
354 int var2 = 2;
355 int var3 = 3;
356 int var4 = 4;
357
358 // No warnings about unused variables even though no check fires and DCHECK
359 // may or may not be enabled.
360 DCHECK(var1) << var2;
361 DPCHECK(var1) << var3;
362 DCHECK_EQ(var1, 1) << var4;
363 }
364
TEST(CheckTest,DCheckEqStatements)365 TEST(CheckTest, DCheckEqStatements) {
366 bool reached = false;
367 if (false)
368 DCHECK_EQ(false, true); // Unreached.
369 else
370 DCHECK_EQ(true, reached = true); // Reached, passed.
371 ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached);
372
373 if (false)
374 DCHECK_EQ(false, true); // Unreached.
375 }
376
TEST(CheckTest,CheckEqStatements)377 TEST(CheckTest, CheckEqStatements) {
378 bool reached = false;
379 if (false)
380 CHECK_EQ(false, true); // Unreached.
381 else
382 CHECK_EQ(true, reached = true); // Reached, passed.
383 ASSERT_TRUE(reached);
384
385 if (false)
386 CHECK_EQ(false, true); // Unreached.
387 }
388
389 #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
TEST(CheckDeathTest,ConfigurableDCheck)390 TEST(CheckDeathTest, ConfigurableDCheck) {
391 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
392 "gtest_internal_run_death_test")) {
393 // This specific test relies on LOGGING_DCHECK not starting out as FATAL,
394 // even when run part of death tests (should die only after LOGGING_DCHECK
395 // gets reconfigured to FATAL below).
396 logging::LOGGING_DCHECK = logging::LOGGING_ERROR;
397 } else {
398 // Verify that DCHECKs default to non-fatal in configurable-DCHECK builds.
399 // Note that we require only that DCHECK is non-fatal by default, rather
400 // than requiring that it be exactly INFO, ERROR, etc level.
401 EXPECT_LT(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
402 }
403 DCHECK(false);
404
405 // Verify that DCHECK* aren't hard-wired to crash on failure.
406 logging::LOGGING_DCHECK = logging::LOGGING_ERROR;
407 DCHECK(false);
408 DCHECK_EQ(1, 2);
409
410 // Verify that DCHECK does crash if LOGGING_DCHECK is set to LOGGING_FATAL.
411 logging::LOGGING_DCHECK = logging::LOGGING_FATAL;
412 EXPECT_CHECK("Check failed: false. ", DCHECK(false));
413 EXPECT_CHECK("Check failed: 1 == 2 (1 vs. 2)", DCHECK_EQ(1, 2));
414 }
415
TEST(CheckTest,ConfigurableDCheckFeature)416 TEST(CheckTest, ConfigurableDCheckFeature) {
417 // Initialize FeatureList with and without DcheckIsFatal, and verify the
418 // value of LOGGING_DCHECK. Note that we don't require that DCHECK take a
419 // specific value when the feature is off, only that it is non-fatal.
420
421 {
422 base::test::ScopedFeatureList feature_list;
423 feature_list.InitFromCommandLine("DcheckIsFatal", "");
424 EXPECT_EQ(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
425 }
426
427 {
428 base::test::ScopedFeatureList feature_list;
429 feature_list.InitFromCommandLine("", "DcheckIsFatal");
430 EXPECT_LT(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
431 }
432
433 // The default case is last, so we leave LOGGING_DCHECK in the default state.
434 {
435 base::test::ScopedFeatureList feature_list;
436 feature_list.InitFromCommandLine("", "");
437 EXPECT_LT(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
438 }
439 }
440 #endif // BUILDFLAG(DCHECK_IS_CONFIGURABLE)
441
442 struct StructWithOstream {
operator ==__anon6bc9643c0111::StructWithOstream443 bool operator==(const StructWithOstream& o) const { return &o == this; }
444 };
445 #if CHECK_WILL_STREAM()
operator <<(std::ostream & out,const StructWithOstream &)446 std::ostream& operator<<(std::ostream& out, const StructWithOstream&) {
447 return out << "ostream";
448 }
449 #endif // CHECK_WILL_STREAM()
450
451 struct StructWithToString {
operator ==__anon6bc9643c0111::StructWithToString452 bool operator==(const StructWithToString& o) const { return &o == this; }
ToString__anon6bc9643c0111::StructWithToString453 std::string ToString() const { return "ToString"; }
454 };
455
456 struct StructWithToStringAndOstream {
operator ==__anon6bc9643c0111::StructWithToStringAndOstream457 bool operator==(const StructWithToStringAndOstream& o) const {
458 return &o == this;
459 }
ToString__anon6bc9643c0111::StructWithToStringAndOstream460 std::string ToString() const { return "ToString"; }
461 };
462 #if CHECK_WILL_STREAM()
operator <<(std::ostream & out,const StructWithToStringAndOstream &)463 std::ostream& operator<<(std::ostream& out,
464 const StructWithToStringAndOstream&) {
465 return out << "ostream";
466 }
467 #endif // CHECK_WILL_STREAM()
468
469 struct StructWithToStringNotStdString {
470 struct PseudoString {};
471
operator ==__anon6bc9643c0111::StructWithToStringNotStdString472 bool operator==(const StructWithToStringNotStdString& o) const {
473 return &o == this;
474 }
ToString__anon6bc9643c0111::StructWithToStringNotStdString475 PseudoString ToString() const { return PseudoString(); }
476 };
477 #if CHECK_WILL_STREAM()
operator <<(std::ostream & out,const StructWithToStringNotStdString::PseudoString &)478 std::ostream& operator<<(std::ostream& out,
479 const StructWithToStringNotStdString::PseudoString&) {
480 return out << "ToString+ostream";
481 }
482 #endif // CHECK_WILL_STREAM()
483
TEST(CheckDeathTest,OstreamVsToString)484 TEST(CheckDeathTest, OstreamVsToString) {
485 StructWithOstream a, b;
486 EXPECT_CHECK("Check failed: a == b (ostream vs. ostream)", CHECK_EQ(a, b));
487
488 StructWithToString c, d;
489 EXPECT_CHECK("Check failed: c == d (ToString vs. ToString)", CHECK_EQ(c, d));
490
491 StructWithToStringAndOstream e, f;
492 EXPECT_CHECK("Check failed: e == f (ostream vs. ostream)", CHECK_EQ(e, f));
493
494 StructWithToStringNotStdString g, h;
495 EXPECT_CHECK("Check failed: g == h (ToString+ostream vs. ToString+ostream)",
496 CHECK_EQ(g, h));
497 }
498
499 // This non-void function is here to make sure that NOTREACHED_NORETURN() is
500 // properly annotated as [[noreturn]] and does not require a return statement.
NotReachedNoreturnInFunction()501 int NotReachedNoreturnInFunction() {
502 NOTREACHED_NORETURN();
503 // No return statement here.
504 }
505
TEST(CheckDeathTest,NotReached)506 TEST(CheckDeathTest, NotReached) {
507 #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
508 // This specific death test relies on LOGGING_DCHECK not being FATAL, even
509 // when run as part of a death test.
510 ScopedDcheckSeverity dcheck_severity(logging::LOGGING_ERROR);
511 #endif
512
513 #if DCHECK_IS_ON()
514 // Expect a DCHECK with streamed params intact.
515 EXPECT_DCHECK("Check failed: false. foo", NOTREACHED() << "foo");
516 #elif CHECK_WILL_STREAM() || BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED)
517 // This block makes sure that base::Location::Current() returns non-dummy
518 // values for file_name() and line_number(). This is necessary to avoid a
519 // false negative inside EXPECT_LOG_ERROR_WITH_FILENAME() where we exhonorate
520 // the NOTREACHED() macro below even though it didn't provide the expected
521 // filename and line numbers.
522 // See EXPECT_LOG_ERROR_WITH_FILENAME() for the exclusion of "" and -1.
523 ASSERT_NE(base::Location::Current().file_name(), nullptr);
524 EXPECT_STRNE(base::Location::Current().file_name(), "");
525 EXPECT_NE(base::Location::Current().line_number(), -1);
526 // Expect LOG(ERROR) that looks like CHECK(false) with streamed params intact.
527 // Note that this implementation uses base::Location::Current() which doesn't
528 // match __FILE__ (strips ../../ prefix) and __LINE__ (uses __builtin_LINE()).
529 EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
530 base::Location::Current().line_number(),
531 NOTREACHED() << "foo",
532 "Check failed: false. foo\n");
533 #else
534 // Expect LOG(ERROR) that looks like CHECK(false) without file or line intact.
535 // We use `""` and `-1` to not expect a specific filename or line number.
536 // The actual location comes from
537 // logging::NotReachedError::TriggerNotReached() but we have no good way of
538 // asserting what that filename or line number is from here.
539 EXPECT_LOG_ERROR_WITH_FILENAME("", -1, NOTREACHED() << "foo",
540 "Check failed: false. NOTREACHED log messages "
541 "are omitted in official builds. Sorry!\n");
542 #endif
543 EXPECT_DEATH_IF_SUPPORTED(NotReachedNoreturnInFunction(),
544 CHECK_WILL_STREAM() ? "NOTREACHED hit. " : "");
545 }
546
TEST(CheckDeathTest,NotReachedFatalExperiment)547 TEST(CheckDeathTest, NotReachedFatalExperiment) {
548 base::test::ScopedFeatureList feature_list(
549 base::features::kNotReachedIsFatal);
550 EXPECT_CHECK_DEATH(NOTREACHED());
551 }
552
TEST(CheckDeathTest,DumpWillBeCheck)553 TEST(CheckDeathTest, DumpWillBeCheck) {
554 DUMP_WILL_BE_CHECK(true);
555
556 EXPECT_DUMP_WILL_BE_CHECK("Check failed: false. foo",
557 DUMP_WILL_BE_CHECK(false) << "foo");
558 }
559
TEST(CheckDeathTest,DumpWillBeNotReachedNoreturn)560 TEST(CheckDeathTest, DumpWillBeNotReachedNoreturn) {
561 EXPECT_DUMP_WILL_BE_CHECK("NOTREACHED hit. foo",
562 DUMP_WILL_BE_NOTREACHED_NORETURN() << "foo");
563 }
564
565 static const std::string kNotImplementedMessage = "Not implemented reached in ";
566
TEST(CheckTest,NotImplemented)567 TEST(CheckTest, NotImplemented) {
568 static const std::string expected_msg =
569 kNotImplementedMessage + __PRETTY_FUNCTION__;
570
571 #if DCHECK_IS_ON()
572 // Expect LOG(ERROR) with streamed params intact.
573 EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
574 base::Location::Current().line_number(),
575 NOTIMPLEMENTED() << "foo",
576 expected_msg + "foo\n");
577 #else
578 // Expect nothing.
579 EXPECT_NO_LOG(NOTIMPLEMENTED() << "foo");
580 #endif
581 }
582
NiLogOnce()583 void NiLogOnce() {
584 NOTIMPLEMENTED_LOG_ONCE();
585 }
586
TEST(CheckTest,NotImplementedLogOnce)587 TEST(CheckTest, NotImplementedLogOnce) {
588 static const std::string expected_msg =
589 kNotImplementedMessage + "void (anonymous namespace)::NiLogOnce()\n";
590
591 #if DCHECK_IS_ON()
592 EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
593 base::Location::Current().line_number() - 10,
594 NiLogOnce(), expected_msg);
595 EXPECT_NO_LOG(NiLogOnce());
596 #else
597 EXPECT_NO_LOG(NiLogOnce());
598 EXPECT_NO_LOG(NiLogOnce());
599 #endif
600 }
601
NiLogTenTimesWithStream()602 void NiLogTenTimesWithStream() {
603 for (int i = 0; i < 10; ++i) {
604 NOTIMPLEMENTED_LOG_ONCE() << " iteration: " << i;
605 }
606 }
607
TEST(CheckTest,NotImplementedLogOnceWithStreamedParams)608 TEST(CheckTest, NotImplementedLogOnceWithStreamedParams) {
609 static const std::string expected_msg1 =
610 kNotImplementedMessage +
611 "void (anonymous namespace)::NiLogTenTimesWithStream() iteration: 0\n";
612
613 #if DCHECK_IS_ON()
614 // Expect LOG(ERROR) with streamed params intact, exactly once.
615 EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
616 base::Location::Current().line_number() - 13,
617 NiLogTenTimesWithStream(), expected_msg1);
618 // A different NOTIMPLEMENTED_LOG_ONCE() call is still logged.
619 static const std::string expected_msg2 =
620 kNotImplementedMessage + __PRETTY_FUNCTION__ + "tree fish\n";
621 EXPECT_LOG_ERROR_WITH_FILENAME(base::Location::Current().file_name(),
622 base::Location::Current().line_number(),
623 NOTIMPLEMENTED_LOG_ONCE() << "tree fish",
624 expected_msg2);
625
626 #else
627 // Expect nothing.
628 EXPECT_NO_LOG(NiLogTenTimesWithStream());
629 EXPECT_NO_LOG(NOTIMPLEMENTED_LOG_ONCE() << "tree fish");
630 #endif
631 }
632
633 // Test CHECK_DEREF of `T*`
TEST(CheckTest,CheckDerefOfPointer)634 TEST(CheckTest, CheckDerefOfPointer) {
635 std::string pointee = "not-null";
636 std::string* value_pointer = &pointee;
637
638 auto& deref_result = CHECK_DEREF(value_pointer);
639 static_assert(std::is_lvalue_reference_v<decltype(deref_result)>);
640 // Compare the pointers to ensure they are the same object (and not a copy)
641 EXPECT_EQ(&deref_result, &pointee);
642 static_assert(std::is_same_v<decltype(deref_result), std::string&>);
643 }
644
TEST(CheckDeathTest,CheckDerefOfNullPointer)645 TEST(CheckDeathTest, CheckDerefOfNullPointer) {
646 std::string* null_pointer = nullptr;
647 EXPECT_CHECK("Check failed: null_pointer != nullptr. ",
648 CHECK_DEREF(null_pointer));
649 }
650
651 // Test CHECK_DEREF of `const T*`
TEST(CheckTest,CheckDerefOfConstPointer)652 TEST(CheckTest, CheckDerefOfConstPointer) {
653 std::string pointee = "not-null";
654 const std::string* const_value_pointer = &pointee;
655
656 auto& deref_result = CHECK_DEREF(const_value_pointer);
657 static_assert(std::is_lvalue_reference_v<decltype(deref_result)>);
658 // Compare the pointers to ensure they are the same object (and not a copy)
659 EXPECT_EQ(&deref_result, &pointee);
660 static_assert(std::is_same_v<decltype(deref_result), const std::string&>);
661 }
662
TEST(CheckDeathTest,CheckDerefOfConstNullPointer)663 TEST(CheckDeathTest, CheckDerefOfConstNullPointer) {
664 std::string* const_null_pointer = nullptr;
665 EXPECT_CHECK("Check failed: const_null_pointer != nullptr. ",
666 CHECK_DEREF(const_null_pointer));
667 }
668
TEST(CheckDeathTest,CheckNotFatalUntil)669 TEST(CheckDeathTest, CheckNotFatalUntil) {
670 #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
671 // This specific death test relies on LOGGING_DCHECK not being FATAL, even
672 // when run as part of a death test, as CHECK with a milestone acts like a
673 // DCHECK.
674 ScopedDcheckSeverity dcheck_severity(logging::LOGGING_ERROR);
675 #endif
676
677 // Next milestone not yet fatal.
678 EXPECT_DUMP_WILL_BE_CHECK("Check failed: false. foo",
679 CHECK(false, kNextMilestone) << "foo");
680
681 // Fatal in current major version.
682 EXPECT_CHECK("Check failed: false. foo", CHECK(false, kCurrentMilestone)
683 << "foo");
684 }
685
TEST(CheckDeathTest,CheckOpNotFatalUntil)686 TEST(CheckDeathTest, CheckOpNotFatalUntil) {
687 #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
688 // This specific death test relies on LOGGING_DCHECK not being FATAL, even
689 // when run as part of a death test, as CHECK with a milestone acts like a
690 // DCHECK.
691 ScopedDcheckSeverity dcheck_severity(logging::LOGGING_ERROR);
692 #endif
693 const int a = 1, b = 2;
694
695 // Next milestone not yet fatal.
696 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a == b (1 vs. 2)",
697 CHECK_EQ(a, b, kNextMilestone));
698 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a != a (1 vs. 1)",
699 CHECK_NE(a, a, kNextMilestone));
700 EXPECT_DUMP_WILL_BE_CHECK("Check failed: b <= a (2 vs. 1)",
701 CHECK_LE(b, a, kNextMilestone));
702 EXPECT_DUMP_WILL_BE_CHECK("Check failed: b < a (2 vs. 1)",
703 CHECK_LT(b, a, kNextMilestone));
704 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a >= b (1 vs. 2)",
705 CHECK_GE(a, b, kNextMilestone));
706 EXPECT_DUMP_WILL_BE_CHECK("Check failed: a > b (1 vs. 2)",
707 CHECK_GT(a, b, kNextMilestone));
708
709 // Fatal in current major version.
710 EXPECT_CHECK("Check failed: a == b (1 vs. 2)",
711 CHECK_EQ(a, b, kCurrentMilestone));
712 EXPECT_CHECK("Check failed: a != a (1 vs. 1)",
713 CHECK_NE(a, a, kCurrentMilestone));
714 EXPECT_CHECK("Check failed: b <= a (2 vs. 1)",
715 CHECK_LE(b, a, kCurrentMilestone));
716 EXPECT_CHECK("Check failed: b < a (2 vs. 1)",
717 CHECK_LT(b, a, kCurrentMilestone));
718 EXPECT_CHECK("Check failed: a >= b (1 vs. 2)",
719 CHECK_GE(a, b, kCurrentMilestone));
720 EXPECT_CHECK("Check failed: a > b (1 vs. 2)",
721 CHECK_GT(a, b, kCurrentMilestone));
722 }
723
TEST(CheckDeathTest,NotReachedNotFatalUntil)724 TEST(CheckDeathTest, NotReachedNotFatalUntil) {
725 #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
726 // This specific death test relies on LOGGING_DCHECK not being FATAL, even
727 // when run as part of a death test, as CHECK with a milestone acts like a
728 // DCHECK.
729 ScopedDcheckSeverity dcheck_severity(logging::LOGGING_ERROR);
730 #endif
731
732 // Next milestone not yet fatal.
733 EXPECT_DUMP_WILL_BE_CHECK("Check failed: false. foo",
734 NOTREACHED(kNextMilestone) << "foo");
735
736 // Fatal in current major version.
737 EXPECT_CHECK("Check failed: false. foo", NOTREACHED(kCurrentMilestone)
738 << "foo");
739 }
740
741 } // namespace
742