xref: /aosp_15_r20/external/cronet/base/check_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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