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

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}
482 lines
16 KiB
C++
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
|