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