| Index: base/logging_unittest.cc
|
| diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
|
| index 8b9701a545fbf99415bcf9f640c2000380ed7549..17836e9b9ef41ef88e47a51a5f7e8b23f635e58f 100644
|
| --- a/base/logging_unittest.cc
|
| +++ b/base/logging_unittest.cc
|
| @@ -24,6 +24,74 @@ void LogSink(const std::string& str) {
|
| }
|
| #endif
|
|
|
| +template <int N>
|
| +class ExpectNLogs {
|
| + public:
|
| + ExpectNLogs() : previous_log_sing_call_count_(log_sink_call_count) {}
|
| + virtual ~ExpectNLogs() {
|
| + EXPECT_EQ(previous_log_sing_call_count_ + N, log_sink_call_count);
|
| + }
|
| +
|
| + private:
|
| + int n_;
|
| + int previous_log_sing_call_count_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ExpectNLogs);
|
| +};
|
| +
|
| +using ExpectNoLogs = ExpectNLogs<0>;
|
| +using ExpectOneLog = ExpectNLogs<1>;
|
| +using ExpectOneLogIfDCheckIsOn = ExpectNLogs<DCHECK_IS_ON() ? 1 : 0>;
|
| +
|
| +class NeverEvaluated {
|
| + public:
|
| + NeverEvaluated() {}
|
| + virtual ~NeverEvaluated() {}
|
| + operator bool() {
|
| + LOG(FATAL) << "Unexpectedly evaluated.";
|
| + return false;
|
| + };
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(NeverEvaluated);
|
| +};
|
| +
|
| +class EvaluatedOnce {
|
| + public:
|
| + explicit EvaluatedOnce(bool value) : value_(value) {}
|
| + virtual ~EvaluatedOnce() {
|
| + LOG_IF(FATAL, evaluations_ != 1)
|
| + << "Expected to be evaluated exactly once.";
|
| + }
|
| +
|
| + operator bool() {
|
| + LOG_IF(FATAL, evaluations_ > 0)
|
| + << "Unexpectedly evaluated more than once.";
|
| + ++evaluations_;
|
| + return value_;
|
| + };
|
| +
|
| + private:
|
| + bool value_;
|
| + int evaluations_ = 0;
|
| + DISALLOW_COPY_AND_ASSIGN(EvaluatedOnce);
|
| +};
|
| +
|
| +#if DCHECK_IS_ON()
|
| +class EvaluatedOnceIfDCheckIsOn : public EvaluatedOnce {
|
| + public:
|
| + EvaluatedOnceIfDCheckIsOn(bool value) : EvaluatedOnce(value) {}
|
| +#else
|
| +class EvaluatedOnceIfDCheckIsOn : public NeverEvaluated {
|
| + public:
|
| + EvaluatedOnceIfDCheckIsOn(bool /* value */) {}
|
| +#endif // DCHECK_IS_ON
|
| + ~EvaluatedOnceIfDCheckIsOn() override {}
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(EvaluatedOnceIfDCheckIsOn);
|
| +};
|
| +
|
| // Class to make sure any manipulations we do to the min log level are
|
| // contained (i.e., do not affect other unit tests).
|
| class LogStateSaver {
|
| @@ -234,6 +302,361 @@ TEST_F(LoggingTest, DcheckReleaseBehavior) {
|
| DCHECK_EQ(some_variable, 1) << "test";
|
| }
|
|
|
| +// Test that DCHECK acts as a single statement in variety of syntactice
|
| +// situations.
|
| +TEST_F(LoggingTest, DCheckStatements) {
|
| + SetLogAssertHandler(&LogSink);
|
| +
|
| + {
|
| + EvaluatedOnceIfDCheckIsOn bool_expr(true);
|
| + NeverEvaluated bool_expr_unreached;
|
| + ExpectNoLogs expect_no_logs;
|
| + if (false)
|
| + DCHECK(bool_expr_unreached);
|
| + else
|
| + DCHECK(bool_expr);
|
| + }
|
| +
|
| + {
|
| + EvaluatedOnceIfDCheckIsOn bool_expr(true);
|
| + NeverEvaluated bool_expr_unreached;
|
| + ExpectNoLogs expect_no_logs;
|
| + if (true)
|
| + DCHECK(bool_expr);
|
| + else
|
| + DCHECK(bool_expr_unreached);
|
| + }
|
| +
|
| + {
|
| + EvaluatedOnceIfDCheckIsOn bool_expr(true);
|
| + NeverEvaluated bool_expr_unreached;
|
| + ExpectNoLogs expect_no_logs;
|
| + switch (2) {
|
| + case 1:
|
| + DCHECK(bool_expr_unreached);
|
| + case 2:
|
| + DCHECK(bool_expr);
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Cases with failing checks.
|
| + {
|
| + EvaluatedOnceIfDCheckIsOn bool_expr_false(false);
|
| + NeverEvaluated bool_expr_unreached;
|
| + ExpectOneLogIfDCheckIsOn expect_one_dlog;
|
| + if (false)
|
| + DCHECK(bool_expr_unreached);
|
| + else
|
| + DCHECK(bool_expr_false);
|
| + }
|
| +
|
| + {
|
| + EvaluatedOnceIfDCheckIsOn bool_expr_false(false);
|
| + NeverEvaluated bool_expr_unreached;
|
| + ExpectOneLogIfDCheckIsOn expect_one_dlog;
|
| + if (true)
|
| + DCHECK(bool_expr_false);
|
| + else
|
| + DCHECK(bool_expr_unreached);
|
| + }
|
| +
|
| + {
|
| + EvaluatedOnceIfDCheckIsOn bool_expr_false(false);
|
| + NeverEvaluated bool_expr_unreached;
|
| + ExpectOneLogIfDCheckIsOn expect_one_dlog;
|
| + switch (2) {
|
| + case 1:
|
| + DCHECK(bool_expr_unreached);
|
| + case 2:
|
| + DCHECK(bool_expr_false);
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST_F(LoggingTest, CheckStatements) {
|
| + SetLogAssertHandler(&LogSink);
|
| +
|
| + EXPECT_EQ(0, log_sink_call_count);
|
| +
|
| + bool reached = false;
|
| + if (false)
|
| + CHECK(false);
|
| + else
|
| + CHECK(reached = true);
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + CHECK(reached = true);
|
| + else
|
| + CHECK(false);
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + switch (2) {
|
| + case 1:
|
| + CHECK(false);
|
| + case 2:
|
| + CHECK(reached=true);
|
| + default:
|
| + break;
|
| + }
|
| + ASSERT_TRUE(reached);
|
| +
|
| + // Cases with failing checks.
|
| + EXPECT_EQ(0, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + CHECK(reached = true);
|
| + else
|
| + CHECK(false);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(1, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + CHECK(false);
|
| + else
|
| + CHECK(reached = true);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(2, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + switch (2) {
|
| + case 1:
|
| + CHECK(reached = true);
|
| + case 2:
|
| + CHECK(false);
|
| + default:
|
| + break;
|
| + }
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(3, log_sink_call_count);
|
| +}
|
| +
|
| +TEST_F(LoggingTest, DCheckEqStatements) {
|
| + SetLogAssertHandler(&LogSink);
|
| +
|
| + EXPECT_EQ(0, log_sink_call_count);
|
| +
|
| + bool reached = false;
|
| + if (false)
|
| + DCHECK_EQ(false, true);
|
| + else
|
| + DCHECK_EQ(true, reached = true);
|
| + ASSERT_EQ(DCHECK_IS_ON(), reached);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + DCHECK_EQ(true, reached = true);
|
| + else
|
| + DCHECK_EQ(false, true);
|
| + ASSERT_EQ(DCHECK_IS_ON(), reached);
|
| +
|
| + reached = false;
|
| + switch (2) {
|
| + case 1:
|
| + DCHECK_EQ(false, true);
|
| + case 2:
|
| + DCHECK_EQ(true, reached=true);
|
| + default:
|
| + break;
|
| + }
|
| + ASSERT_EQ(DCHECK_IS_ON(), reached);
|
| +
|
| + // Cases with failing checks.
|
| + EXPECT_EQ(0, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + DCHECK_EQ(true, reached = true);
|
| + else
|
| + DCHECK_EQ(false, true);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + DCHECK_EQ(false, true);
|
| + else
|
| + DCHECK_EQ(true, reached = true);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + switch (2) {
|
| + case 1:
|
| + DCHECK_EQ(true, reached = true);
|
| + case 2:
|
| + DCHECK_EQ(false, true);
|
| + default:
|
| + break;
|
| + }
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + DCHECK_EQ(false, reached = true);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count);
|
| +}
|
| +
|
| +TEST_F(LoggingTest, CheckEqStatements) {
|
| + SetLogAssertHandler(&LogSink);
|
| +
|
| + EXPECT_EQ(0, log_sink_call_count);
|
| +
|
| + bool reached = false;
|
| + if (false)
|
| + CHECK_EQ(false, true);
|
| + else
|
| + CHECK_EQ(true, reached = true);
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + CHECK_EQ(true, reached = true);
|
| + else
|
| + CHECK_EQ(false, true);
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + switch (2) {
|
| + case 1:
|
| + CHECK_EQ(false, true);
|
| + case 2:
|
| + CHECK_EQ(true, reached = true);
|
| + default:
|
| + break;
|
| + }
|
| + ASSERT_TRUE(reached);
|
| +
|
| + // Cases with failing checks.
|
| + EXPECT_EQ(0, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + CHECK_EQ(true, reached = true);
|
| + else
|
| + CHECK_EQ(false, true);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(1, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + CHECK_EQ(false, true);
|
| + else
|
| + CHECK_EQ(true, reached = true);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(2, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + switch (2) {
|
| + case 1:
|
| + CHECK_EQ(true, reached = true);
|
| + case 2:
|
| + CHECK_EQ(false, true);
|
| + default:
|
| + break;
|
| + }
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(3, log_sink_call_count);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + CHECK_EQ(false, reached = true);
|
| + ASSERT_FALSE(reached);
|
| + ASSERT_EQ(3, log_sink_call_count);
|
| +}
|
| +
|
| +TEST_F(LoggingTest, LogStatements) {
|
| + bool reached = false;
|
| + if (true)
|
| + LOG(INFO) << "Hello: " << (reached = true);
|
| + else
|
| + LOG(FATAL) << "Goodbye.";
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + LOG(FATAL) << "Goodbye.";
|
| + else
|
| + LOG(INFO) << "Hello: " << (reached = true);
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + LOG_IF(INFO, reached = true) << "Hello.";
|
| + else
|
| + LOG_IF(FATAL, true) << "Goodbye.";
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + LOG_IF(FATAL, true) << "Goodbye.";
|
| + else
|
| + LOG_IF(INFO, reached = true) << "Hello.";
|
| + ASSERT_TRUE(reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + LOG_IF(FATAL, true) << "Goodbye.";
|
| + else
|
| + LOG_IF(INFO, false) << "Derp: " << (reached = true);
|
| + ASSERT_FALSE(reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + LOG_IF(FATAL, reached = true) << "Goodbye.";
|
| + ASSERT_FALSE(reached);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + DLOG(INFO) << "Hello: " << (reached = true);
|
| + else
|
| + DLOG(FATAL) << "Goodbye.";
|
| + ASSERT_EQ(DLOG_IS_ON(INFO), reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + DLOG(FATAL) << "Goodbye.";
|
| + else
|
| + DLOG(INFO) << "Hello: " << (reached = true);
|
| + ASSERT_EQ(DLOG_IS_ON(INFO), reached);
|
| +
|
| + reached = false;
|
| + if (true)
|
| + DLOG_IF(INFO, true) << "Hello: " << (reached = true);
|
| + else
|
| + DLOG_IF(FATAL, true) << "Goodbye.";
|
| + ASSERT_EQ(DLOG_IS_ON(INFO), reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + DLOG_IF(FATAL, true) << "Goodbye.";
|
| + else
|
| + DLOG_IF(INFO, true) << "Hello: " << (reached = true);
|
| + ASSERT_EQ(DLOG_IS_ON(INFO), reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + DLOG_IF(FATAL, true) << "Goodbye.";
|
| + else
|
| + DLOG_IF(INFO, false) << "Derp: " << (reached = true);
|
| + ASSERT_FALSE(reached);
|
| +
|
| + reached = false;
|
| + if (false)
|
| + DLOG_IF(FATAL, reached = true) << "Goodbye.";
|
| + ASSERT_FALSE(reached);
|
| +}
|
| +
|
| // Test that defining an operator<< for a type in a namespace doesn't prevent
|
| // other code in that namespace from calling the operator<<(ostream, wstring)
|
| // defined by logging.h. This can fail if operator<<(ostream, wstring) can't be
|
|
|