0
Files
android_webview
apps
ash
base
allocator
android
containers
debug
files
fuchsia
functional
hash
i18n
ios
json
mac
memory
message_loop
metrics
nix
numerics
posix
power_monitor
process
profiler
ranges
sampling_heap_profiler
strings
synchronization
system
task
test
third_party
threading
time
timer
trace_event
tracing
types
util
win
BUILD.gn
DEPS
DIR_METADATA
OWNERS
PRESUBMIT.py
README.md
SECURITY_OWNERS
as_const.h
as_const_unittest.cc
at_exit.cc
at_exit.h
at_exit_unittest.cc
atomic_ref_count.h
atomic_sequence_num.h
atomicops.h
atomicops_internals_atomicword_compat.h
atomicops_internals_portable.h
atomicops_unittest.cc
auto_reset.h
auto_reset_unittest.cc
barrier_closure.cc
barrier_closure.h
barrier_closure_unittest.cc
base64.cc
base64.h
base64_decode_fuzzer.cc
base64_encode_fuzzer.cc
base64_unittest.cc
base64url.cc
base64url.h
base64url_unittest.cc
base_export.h
base_paths.cc
base_paths.h
base_paths_android.cc
base_paths_android.h
base_paths_fuchsia.cc
base_paths_fuchsia.h
base_paths_mac.h
base_paths_mac.mm
base_paths_posix.cc
base_paths_posix.h
base_paths_win.cc
base_paths_win.h
base_switches.cc
base_switches.h
big_endian.cc
big_endian.h
big_endian_unittest.cc
bind.h
bind_internal.h
bind_post_task.h
bind_post_task_internal.h
bind_post_task_unittest.cc
bind_post_task_unittest.nc
bind_unittest.cc
bind_unittest.nc
bit_cast.h
bit_cast_unittest.cc
bits.h
bits_unittest.cc
build_time.cc
build_time.h
build_time_unittest.cc
callback.h
callback_forward.h
callback_helpers.cc
callback_helpers.h
callback_helpers_unittest.cc
callback_internal.cc
callback_internal.h
callback_list.cc
callback_list.h
callback_list_unittest.cc
callback_list_unittest.nc
callback_unittest.cc
callback_unittest.nc
cancelable_callback.h
cancelable_callback_unittest.cc
check.cc
check.h
check_example.cc
check_op.cc
check_op.h
check_unittest.cc
command_line.cc
command_line.h
command_line_unittest.cc
compiler_specific.h
component_export.h
component_export_unittest.cc
cpu.cc
cpu.h
cpu_affinity_posix.cc
cpu_affinity_posix.h
cpu_affinity_posix_unittest.cc
cpu_unittest.cc
critical_closure.h
critical_closure_internal_ios.mm
cxx17_backports.h
cxx17_backports_unittest.cc
dcheck_is_on.h
deferred_sequenced_task_runner.cc
deferred_sequenced_task_runner.h
deferred_sequenced_task_runner_unittest.cc
enterprise_util.h
enterprise_util_mac.mm
enterprise_util_mac_unittest.mm
enterprise_util_win.cc
environment.cc
environment.h
environment_unittest.cc
export_template.h
feature_list.cc
feature_list.h
feature_list_unittest.cc
file_descriptor_posix.h
file_descriptor_store.cc
file_descriptor_store.h
file_version_info.h
file_version_info_mac.h
file_version_info_mac.mm
file_version_info_win.cc
file_version_info_win.h
file_version_info_win_unittest.cc
format_macros.h
gmock_unittest.cc
gtest_prod_util.h
guid.cc
guid.h
guid_unittest.cc
immediate_crash.h
immediate_crash_unittest.cc
lazy_instance.h
lazy_instance_helpers.cc
lazy_instance_helpers.h
lazy_instance_unittest.cc
linux_util.cc
linux_util.h
linux_util_unittest.cc
location.cc
location.h
location_unittest.cc
logging.cc
logging.h
logging_chromeos.cc
logging_unittest.cc
logging_win.cc
logging_win.h
macros.h
native_library.cc
native_library.h
native_library_fuchsia.cc
native_library_ios.mm
native_library_mac.mm
native_library_posix.cc
native_library_unittest.cc
native_library_win.cc
no_destructor.h
no_destructor_unittest.cc
notreached.cc
notreached.h
observer_list.h
observer_list_internal.cc
observer_list_internal.h
observer_list_perftest.cc
observer_list_threadsafe.cc
observer_list_threadsafe.h
observer_list_threadsafe_unittest.cc
observer_list_types.cc
observer_list_types.h
observer_list_unittest.cc
observer_list_unittest.nc
one_shot_event.cc
one_shot_event.h
one_shot_event_unittest.cc
optional_unittest.cc
os_compat_android.cc
os_compat_android.h
os_compat_android_unittest.cc
os_compat_nacl.cc
os_compat_nacl.h
parameter_pack.h
parameter_pack_unittest.cc
path_service.cc
path_service.h
path_service_unittest.cc
pending_task.cc
pending_task.h
pickle.cc
pickle.h
pickle_fuzzer.cc
pickle_unittest.cc
post_task_and_reply_with_result_internal.h
rand_util.cc
rand_util.h
rand_util_fuchsia.cc
rand_util_nacl.cc
rand_util_posix.cc
rand_util_unittest.cc
rand_util_win.cc
run_loop.cc
run_loop.h
run_loop_unittest.cc
safe_numerics_unittest.cc
scoped_clear_last_error.h
scoped_clear_last_error_unittest.cc
scoped_clear_last_error_win.cc
scoped_generic.h
scoped_generic_unittest.cc
scoped_multi_source_observation.h
scoped_multi_source_observation_unittest.cc
scoped_native_library.cc
scoped_native_library.h
scoped_native_library_unittest.cc
scoped_observation.h
scoped_observation_unittest.cc
security_unittest.cc
sequence_checker.h
sequence_checker_impl.cc
sequence_checker_impl.h
sequence_checker_unittest.cc
sequence_checker_unittest.nc
sequence_token.cc
sequence_token.h
sequence_token_unittest.cc
sequenced_task_runner.cc
sequenced_task_runner.h
sequenced_task_runner_helpers.h
sequenced_task_runner_unittest.cc
single_thread_task_runner.h
stl_util.h
stl_util_unittest.cc
supports_user_data.cc
supports_user_data.h
supports_user_data_unittest.cc
sync_socket.cc
sync_socket.h
sync_socket_nacl.cc
sync_socket_posix.cc
sync_socket_unittest.cc
sync_socket_win.cc
sys_byteorder.h
sys_byteorder_unittest.cc
syslog_logging.cc
syslog_logging.h
task_runner.cc
task_runner.h
task_runner_unittest.cc
task_runner_util.h
task_runner_util_unittest.cc
template_util.h
template_util_unittest.cc
thread_annotations.h
thread_annotations_unittest.cc
thread_annotations_unittest.nc
token.cc
token.h
token_unittest.cc
tools_sanity_unittest.cc
traits_bag.h
traits_bag_unittest.cc
traits_bag_unittest.nc
tuple.h
tuple_unittest.cc
unguessable_token.cc
unguessable_token.h
unguessable_token_unittest.cc
updateable_sequenced_task_runner.h
value_iterators.cc
value_iterators.h
value_iterators_unittest.cc
values.cc
values.h
values_unittest.cc
version.cc
version.h
version_unittest.cc
vlog.cc
vlog.h
vlog_unittest.cc
build
build_overrides
buildtools
cc
chrome
chromecast
chromeos
cloud_print
codelabs
components
content
courgette
crypto
dbus
device
docs
extensions
fuchsia
gin
google_apis
google_update
gpu
headless
infra
ios
ipc
jingle
media
mojo
native_client_sdk
net
pdf
ppapi
printing
remoting
rlz
sandbox
services
skia
sql
storage
styleguide
testing
third_party
tools
ui
url
weblayer
.clang-format
.clang-tidy
.eslintrc.js
.git-blame-ignore-revs
.gitattributes
.gitignore
.gn
.mailmap
.vpython
.vpython3
.yapfignore
AUTHORS
BUILD.gn
CODE_OF_CONDUCT.md
DEPS
DIR_METADATA
ENG_REVIEW_OWNERS
LICENSE
LICENSE.chromium_os
OWNERS
PRESUBMIT.py
PRESUBMIT_test.py
PRESUBMIT_test_mocks.py
README.md
WATCHLISTS
codereview.settings
src/base/check_unittest.cc
Lei Zhang 93dd4257e8 Change logging::LOG_FOO to logging::LOGGING_FOO.
Avoid conflicts with LOG_FOO in sys/syslog.h on Linux.

Convert LOG_FOO to LOGGING_FOO in base/, but leave the rest of the code
base untouched. Keep LOG_FOO defined for now to make it possible to
convert the rest of the code base in smaller increments.

BUG=849450

Change-Id: Icce5121f7cd036e9e9eddd7de68f57474f4ab73c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1086147
Reviewed-by: danakj <danakj@chromium.org>
Reviewed-by: Wez <wez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820349}
2020-10-23 18:45:53 +00:00

482 lines
16 KiB
C++

// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
// Helper class which expects a check to fire with a certain location and
// message before the end of the current scope.
class ScopedCheckExpectation {
public:
ScopedCheckExpectation(const char* file, int line, std::string msg)
: file_(file),
line_(line),
msg_(msg),
assert_handler_(base::BindRepeating(&ScopedCheckExpectation::Check,
base::Unretained(this))),
fired_(false) {}
~ScopedCheckExpectation() {
EXPECT_TRUE(fired_) << "CHECK at " << file_ << ":" << line_
<< " never fired!";
}
private:
void Check(const char* file,
int line,
const base::StringPiece msg,
const base::StringPiece stack) {
fired_ = true;
EXPECT_EQ(file, file_);
EXPECT_EQ(line, line_);
if (msg_.find("=~") == 0) {
EXPECT_THAT(std::string(msg), testing::MatchesRegex(msg_.substr(2)));
} else {
EXPECT_EQ(std::string(msg), msg_);
}
}
std::string file_;
int line_;
std::string msg_;
logging::ScopedLogAssertHandler assert_handler_;
bool fired_;
};
// Macro which expects a CHECK to fire with a certain message. If msg starts
// with "=~", it's interpreted as a regular expression.
// Example: EXPECT_CHECK("Check failed: false.", CHECK(false));
#if defined(OFFICIAL_BUILD) && defined(NDEBUG)
#define EXPECT_CHECK(msg, check_expr) \
do { \
EXPECT_CHECK_DEATH(check_expr); \
} while (0)
#else
#define EXPECT_CHECK(msg, check_expr) \
do { \
ScopedCheckExpectation check_exp(__FILE__, __LINE__, msg); \
check_expr; \
} while (0)
#endif
// Macro which expects a DCHECK to fire if DCHECKs are enabled.
#define EXPECT_DCHECK(msg, check_expr) \
do { \
if (DCHECK_IS_ON() && logging::LOGGING_DCHECK == logging::LOGGING_FATAL) { \
ScopedCheckExpectation check_exp(__FILE__, __LINE__, msg); \
check_expr; \
} else { \
check_expr; \
} \
} while (0)
class CheckTest : public testing::Test {};
TEST_F(CheckTest, Basics) {
EXPECT_CHECK("Check failed: false. ", CHECK(false));
EXPECT_CHECK("Check failed: false. foo", CHECK(false) << "foo");
double a = 2, b = 1;
EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)", CHECK_LT(a, b));
EXPECT_CHECK("Check failed: a < b (2.000000 vs. 1.000000)foo",
CHECK_LT(a, b) << "foo");
}
TEST_F(CheckTest, PCheck) {
const char file[] = "/nonexistentfile123";
ignore_result(fopen(file, "r"));
std::string err =
logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
EXPECT_CHECK(
"Check failed: fopen(file, \"r\") != nullptr."
" : " +
err,
PCHECK(fopen(file, "r") != nullptr));
EXPECT_CHECK(
"Check failed: fopen(file, \"r\") != nullptr."
" foo: " +
err,
PCHECK(fopen(file, "r") != nullptr) << "foo");
EXPECT_DCHECK(
"Check failed: fopen(file, \"r\") != nullptr."
" : " +
err,
DPCHECK(fopen(file, "r") != nullptr));
EXPECT_DCHECK(
"Check failed: fopen(file, \"r\") != nullptr."
" foo: " +
err,
DPCHECK(fopen(file, "r") != nullptr) << "foo");
}
TEST_F(CheckTest, CheckOp) {
int a = 1, b = 2;
// clang-format off
EXPECT_CHECK("Check failed: a == b (1 vs. 2)", CHECK_EQ(a, b));
EXPECT_CHECK("Check failed: a != a (1 vs. 1)", CHECK_NE(a, a));
EXPECT_CHECK("Check failed: b <= a (2 vs. 1)", CHECK_LE(b, a));
EXPECT_CHECK("Check failed: b < a (2 vs. 1)", CHECK_LT(b, a));
EXPECT_CHECK("Check failed: a >= b (1 vs. 2)", CHECK_GE(a, b));
EXPECT_CHECK("Check failed: a > b (1 vs. 2)", CHECK_GT(a, b));
EXPECT_DCHECK("Check failed: a == b (1 vs. 2)", DCHECK_EQ(a, b));
EXPECT_DCHECK("Check failed: a != a (1 vs. 1)", DCHECK_NE(a, a));
EXPECT_DCHECK("Check failed: b <= a (2 vs. 1)", DCHECK_LE(b, a));
EXPECT_DCHECK("Check failed: b < a (2 vs. 1)", DCHECK_LT(b, a));
EXPECT_DCHECK("Check failed: a >= b (1 vs. 2)", DCHECK_GE(a, b));
EXPECT_DCHECK("Check failed: a > b (1 vs. 2)", DCHECK_GT(a, b));
// clang-format on
}
TEST_F(CheckTest, CheckStreamsAreLazy) {
int called_count = 0;
int not_called_count = 0;
auto Called = [&]() {
++called_count;
return 42;
};
auto NotCalled = [&]() {
++not_called_count;
return 42;
};
CHECK(Called()) << NotCalled();
CHECK_EQ(Called(), Called()) << NotCalled();
PCHECK(Called()) << NotCalled();
DCHECK(Called()) << NotCalled();
DCHECK_EQ(Called(), Called()) << NotCalled();
DPCHECK(Called()) << NotCalled();
EXPECT_EQ(not_called_count, 0);
#if DCHECK_IS_ON()
EXPECT_EQ(called_count, 8);
#else
EXPECT_EQ(called_count, 4);
#endif
}
void DcheckEmptyFunction1() {
// Provide a body so that Release builds do not cause the compiler to
// optimize DcheckEmptyFunction1 and DcheckEmptyFunction2 as a single
// function, which breaks the Dcheck tests below.
LOG(INFO) << "DcheckEmptyFunction1";
}
void DcheckEmptyFunction2() {}
#if defined(DCHECK_IS_CONFIGURABLE)
class ScopedDcheckSeverity {
public:
ScopedDcheckSeverity(logging::LogSeverity new_severity)
: old_severity_(logging::LOGGING_DCHECK) {
logging::LOGGING_DCHECK = new_severity;
}
~ScopedDcheckSeverity() { logging::LOGGING_DCHECK = old_severity_; }
private:
logging::LogSeverity old_severity_;
};
#endif // defined(DCHECK_IS_CONFIGURABLE)
// https://crbug.com/709067 tracks test flakiness on iOS.
#if defined(OS_IOS)
#define MAYBE_Dcheck DISABLED_Dcheck
#else
#define MAYBE_Dcheck Dcheck
#endif
TEST_F(CheckTest, MAYBE_Dcheck) {
#if defined(DCHECK_IS_CONFIGURABLE)
// DCHECKs are enabled, and LOGGING_DCHECK is mutable, but defaults to
// non-fatal. Set it to LOGGING_FATAL to get the expected behavior from the
// rest of this test.
ScopedDcheckSeverity dcheck_severity(logging::LOGGING_FATAL);
#endif // defined(DCHECK_IS_CONFIGURABLE)
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
// Release build.
EXPECT_FALSE(DCHECK_IS_ON());
EXPECT_FALSE(DLOG_IS_ON(DCHECK));
#elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
// Release build with real DCHECKS.
EXPECT_TRUE(DCHECK_IS_ON());
EXPECT_TRUE(DLOG_IS_ON(DCHECK));
#else
// Debug build.
EXPECT_TRUE(DCHECK_IS_ON());
EXPECT_TRUE(DLOG_IS_ON(DCHECK));
#endif
EXPECT_DCHECK("Check failed: false. ", DCHECK(false));
std::string err =
logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
EXPECT_DCHECK("Check failed: false. : " + err, DPCHECK(false));
EXPECT_DCHECK("Check failed: 0 == 1 (0 vs. 1)", DCHECK_EQ(0, 1));
// Test DCHECK on std::nullptr_t
const void* p_null = nullptr;
const void* p_not_null = &p_null;
DCHECK_EQ(p_null, nullptr);
DCHECK_EQ(nullptr, p_null);
DCHECK_NE(p_not_null, nullptr);
DCHECK_NE(nullptr, p_not_null);
// Test DCHECK on a scoped enum.
enum class Animal { DOG, CAT };
DCHECK_EQ(Animal::DOG, Animal::DOG);
EXPECT_DCHECK("Check failed: Animal::DOG == Animal::CAT (0 vs. 1)",
DCHECK_EQ(Animal::DOG, Animal::CAT));
// Test DCHECK on functions and function pointers.
struct MemberFunctions {
void MemberFunction1() {
// See the comment in DcheckEmptyFunction1().
LOG(INFO) << "Do not merge with MemberFunction2.";
}
void MemberFunction2() {}
};
void (MemberFunctions::*mp1)() = &MemberFunctions::MemberFunction1;
void (MemberFunctions::*mp2)() = &MemberFunctions::MemberFunction2;
void (*fp1)() = DcheckEmptyFunction1;
void (*fp2)() = DcheckEmptyFunction2;
void (*fp3)() = DcheckEmptyFunction1;
DCHECK_EQ(fp1, fp3);
DCHECK_EQ(mp1, &MemberFunctions::MemberFunction1);
DCHECK_EQ(mp2, &MemberFunctions::MemberFunction2);
EXPECT_DCHECK("=~Check failed: fp1 == fp2 \\(\\w+ vs. \\w+\\)",
DCHECK_EQ(fp1, fp2));
EXPECT_DCHECK(
"Check failed: mp2 == &MemberFunctions::MemberFunction1 (1 vs. 1)",
DCHECK_EQ(mp2, &MemberFunctions::MemberFunction1));
}
TEST_F(CheckTest, DcheckReleaseBehavior) {
int var1 = 1;
int var2 = 2;
int var3 = 3;
int var4 = 4;
// No warnings about unused variables even though no check fires and DCHECK
// may or may not be enabled.
DCHECK(var1) << var2;
DPCHECK(var1) << var3;
DCHECK_EQ(var1, 1) << var4;
}
TEST_F(CheckTest, DCheckEqStatements) {
bool reached = false;
if (false)
DCHECK_EQ(false, true); // Unreached.
else
DCHECK_EQ(true, reached = true); // Reached, passed.
ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached);
if (false)
DCHECK_EQ(false, true); // Unreached.
}
TEST_F(CheckTest, CheckEqStatements) {
bool reached = false;
if (false)
CHECK_EQ(false, true); // Unreached.
else
CHECK_EQ(true, reached = true); // Reached, passed.
ASSERT_TRUE(reached);
if (false)
CHECK_EQ(false, true); // Unreached.
}
#if defined(DCHECK_IS_CONFIGURABLE)
TEST_F(CheckTest, ConfigurableDCheck) {
// Verify that DCHECKs default to non-fatal in configurable-DCHECK builds.
// Note that we require only that DCHECK is non-fatal by default, rather
// than requiring that it be exactly INFO, ERROR, etc level.
EXPECT_LT(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
DCHECK(false);
// Verify that DCHECK* aren't hard-wired to crash on failure.
logging::LOGGING_DCHECK = logging::LOG_INFO;
DCHECK(false);
DCHECK_EQ(1, 2);
// Verify that DCHECK does crash if LOGGING_DCHECK is set to LOGGING_FATAL.
logging::LOGGING_DCHECK = logging::LOGGING_FATAL;
EXPECT_CHECK("Check failed: false. ", DCHECK(false));
EXPECT_CHECK("Check failed: 1 == 2 (1 vs. 2)", DCHECK_EQ(1, 2));
}
TEST_F(CheckTest, ConfigurableDCheckFeature) {
// Initialize FeatureList with and without DcheckIsFatal, and verify the
// value of LOGGING_DCHECK. Note that we don't require that DCHECK take a
// specific value when the feature is off, only that it is non-fatal.
{
base::test::ScopedFeatureList feature_list;
feature_list.InitFromCommandLine("DcheckIsFatal", "");
EXPECT_EQ(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
}
{
base::test::ScopedFeatureList feature_list;
feature_list.InitFromCommandLine("", "DcheckIsFatal");
EXPECT_LT(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
}
// The default case is last, so we leave LOGGING_DCHECK in the default state.
{
base::test::ScopedFeatureList feature_list;
feature_list.InitFromCommandLine("", "");
EXPECT_LT(logging::LOGGING_DCHECK, logging::LOGGING_FATAL);
}
}
#endif // defined(DCHECK_IS_CONFIGURABLE)
struct StructWithOstream {
bool operator==(const StructWithOstream& o) const { return &o == this; }
};
#if !(defined(OFFICIAL_BUILD) && defined(NDEBUG))
std::ostream& operator<<(std::ostream& out, const StructWithOstream&) {
return out << "ostream";
}
#endif
struct StructWithToString {
bool operator==(const StructWithToString& o) const { return &o == this; }
std::string ToString() const { return "ToString"; }
};
struct StructWithToStringAndOstream {
bool operator==(const StructWithToStringAndOstream& o) const {
return &o == this;
}
std::string ToString() const { return "ToString"; }
};
#if !(defined(OFFICIAL_BUILD) && defined(NDEBUG))
std::ostream& operator<<(std::ostream& out,
const StructWithToStringAndOstream&) {
return out << "ostream";
}
#endif
struct StructWithToStringNotStdString {
struct PseudoString {};
bool operator==(const StructWithToStringNotStdString& o) const {
return &o == this;
}
PseudoString ToString() const { return PseudoString(); }
};
#if !(defined(OFFICIAL_BUILD) && defined(NDEBUG))
std::ostream& operator<<(std::ostream& out,
const StructWithToStringNotStdString::PseudoString&) {
return out << "ToString+ostream";
}
#endif
TEST_F(CheckTest, OstreamVsToString) {
StructWithOstream a, b;
EXPECT_CHECK("Check failed: a == b (ostream vs. ostream)", CHECK_EQ(a, b));
StructWithToString c, d;
EXPECT_CHECK("Check failed: c == d (ToString vs. ToString)", CHECK_EQ(c, d));
StructWithToStringAndOstream e, f;
EXPECT_CHECK("Check failed: e == f (ostream vs. ostream)", CHECK_EQ(e, f));
StructWithToStringNotStdString g, h;
EXPECT_CHECK("Check failed: g == h (ToString+ostream vs. ToString+ostream)",
CHECK_EQ(g, h));
}
#define EXPECT_LOG_ERROR(msg, expr, expected_line) \
do { \
static bool got_log_message = false; \
ASSERT_EQ(logging::GetLogMessageHandler(), nullptr); \
logging::SetLogMessageHandler([](int severity, const char* file, int line, \
size_t message_start, \
const std::string& str) { \
EXPECT_FALSE(got_log_message); \
got_log_message = true; \
EXPECT_EQ(severity, logging::LOG_ERROR); \
EXPECT_EQ(str.substr(message_start), (msg)); \
EXPECT_STREQ(__FILE__, file); \
EXPECT_EQ(expected_line, line); \
return true; \
}); \
expr; \
EXPECT_TRUE(got_log_message); \
logging::SetLogMessageHandler(nullptr); \
} while (0)
#define EXPECT_NO_LOG(expr) \
do { \
ASSERT_EQ(logging::GetLogMessageHandler(), nullptr); \
logging::SetLogMessageHandler([](int severity, const char* file, int line, \
size_t message_start, \
const std::string& str) { \
EXPECT_TRUE(false) << "Unexpected log: " << str; \
return true; \
}); \
expr; \
logging::SetLogMessageHandler(nullptr); \
} while (0)
TEST_F(CheckTest, NotReached) {
#if BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED)
// Expect LOG(ERROR) without the streamed params.
EXPECT_LOG_ERROR("NOTREACHED() hit.\n", NOTREACHED() << "foo", __LINE__);
#else
// Expect a DCHECK with streamed params intact.
EXPECT_DCHECK("Check failed: false. foo", NOTREACHED() << "foo");
#endif
}
TEST_F(CheckTest, NotImplemented) {
static const std::string expected_msg =
std::string("Not implemented reached in ") + __PRETTY_FUNCTION__;
#if DCHECK_IS_ON()
// Expect LOG(ERROR) with streamed params intact.
EXPECT_LOG_ERROR(expected_msg + "foo\n", NOTIMPLEMENTED() << "foo", __LINE__);
#else
// Expect nothing.
EXPECT_NO_LOG(NOTIMPLEMENTED() << "foo");
#endif
}
void NiLogOnce() {
// Note: The stream param is not logged.
NOTIMPLEMENTED_LOG_ONCE() << "foo";
}
TEST_F(CheckTest, NotImplementedLogOnce) {
static const std::string expected_msg =
"Not implemented reached in void (anonymous namespace)::NiLogOnce()\n";
#if DCHECK_IS_ON()
EXPECT_LOG_ERROR(expected_msg, NiLogOnce(), __LINE__ - 8);
EXPECT_NO_LOG(NiLogOnce());
#else
EXPECT_NO_LOG(NiLogOnce());
EXPECT_NO_LOG(NiLogOnce());
#endif
}
} // namespace