Chromium Code Reviews| Index: base/logging_unittest.cc |
| diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc |
| index 8b9701a545fbf99415bcf9f640c2000380ed7549..765067b03733a1e81e456186e7ca1170573b97e5 100644 |
| --- a/base/logging_unittest.cc |
| +++ b/base/logging_unittest.cc |
| @@ -42,6 +42,61 @@ class LogStateSaver { |
| DISALLOW_COPY_AND_ASSIGN(LogStateSaver); |
| }; |
| +// Validates that exactly N log messages are received during its lifetime. |
| +template <int N> |
| +class ExpectNLogs { |
| + public: |
| + ExpectNLogs() { |
| + SetLogAssertHandler(&LogSink); |
| + log_sink_call_count = 0; |
| + } |
| + |
| + ~ExpectNLogs() { |
| + SetLogAssertHandler(NULL); |
| + EXPECT_EQ(N, log_sink_call_count); |
| + } |
| + |
| + private: |
| + LogStateSaver log_state_saver_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ExpectNLogs); |
| +}; |
| + |
| +using ExpectNoLogs = ExpectNLogs<0>; |
| +using ExpectOneLog = ExpectNLogs<1>; |
| +using ExpectOneLogIfDCheckIsOn = ExpectNLogs<DCHECK_IS_ON() ? 1 : 0>; |
| + |
| +// A convenience function to aid in test readability. |
| +bool UnreachedBoolExpr() { |
| + ADD_FAILURE() << "Unexpectedly evaluated."; |
| + return false; |
| +} |
| + |
| +// Validates that operator()() is invoked exactly N times. |
| +template<int N> |
| +class EvaluatedNTimes { |
| + public: |
| + EvaluatedNTimes() {} |
| + ~EvaluatedNTimes() { |
| + EXPECT_EQ(N, evaluations_) << "Expected to be evaluated exactly " << N |
| + << " times."; |
| + } |
| + |
| + bool operator()() { |
| + EXPECT_GT(N, evaluations_) << "Evaluated more than the expected " << N |
| + << " times."; |
| + ++evaluations_; |
| + return true; |
| + }; |
| + |
| + private: |
| + int evaluations_ = 0; |
| + DISALLOW_COPY_AND_ASSIGN(EvaluatedNTimes); |
| +}; |
| + |
| +using EvaluatedOnce = EvaluatedNTimes<1>; |
| +using EvaluatedOnceIfDCheckIsOn = EvaluatedNTimes<DCHECK_IS_ON() ? 1 : 0>; |
| + |
| class LoggingTest : public testing::Test { |
| private: |
| LogStateSaver log_state_saver_; |
| @@ -234,6 +289,636 @@ TEST_F(LoggingTest, DcheckReleaseBehavior) { |
| DCHECK_EQ(some_variable, 1) << "test"; |
| } |
| +// Test that DCHECK acts as a single statement in variety of syntactic |
| +// situations. |
| +TEST_F(LoggingTest, DCheckStatements) { |
| + // The next three blocks validate that the DCHECK is correctly bound to the |
| + // 'if' statement. |
| + { |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached DCHECK. |
| + if (false) |
| + DCHECK(UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
|
Sigurður Ásgeirsson
2015/07/16 10:51:28
nit: IMHO the use of this would be marginally more
|
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Reached, successful DCHECK. |
| + if (true) |
| + DCHECK(bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Reached, failed DCHECK. |
| + if (true) |
| + DCHECK(!bool_expr()); |
| + } |
| + |
| + // The following four cases validate that the DCHECK is correctly bound in an |
| + // 'if/else' statement. |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached if, successful else. |
| + if (false) |
| + DCHECK(UnreachedBoolExpr()); |
| + else |
| + DCHECK(bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Successful if, unreached else. |
| + if (true) |
| + DCHECK(bool_expr()); |
| + else |
| + DCHECK(UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Unreached if, failed else. |
| + if (false) |
| + DCHECK(UnreachedBoolExpr()); |
| + else |
| + DCHECK(!bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Failed if, unreached else. |
| + if (true) |
| + DCHECK(!bool_expr()); |
| + else |
| + DCHECK(UnreachedBoolExpr()); |
| + } |
| + |
| + // These cases validate that a DCHECK may appear in a switch statement. |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + switch (2) { |
| + case 1: |
| + DCHECK(UnreachedBoolExpr()); |
| + case 2: |
| + DCHECK(bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + switch (2) { |
| + case 1: |
| + DCHECK(UnreachedBoolExpr()); |
| + case 2: |
| + DCHECK(!bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| +} |
| + |
| +// Test that CHECK acts as a single statement in variety of syntactic |
| +// situations. |
| +TEST_F(LoggingTest, CheckStatements) { |
| + // The next three blocks validate that the CHECK is correctly bound to the |
| + // 'if' statement. |
| + { |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached CHECK. |
| + if (false) |
| + CHECK(UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Reached, successful CHECK. |
| + if (true) |
| + CHECK(bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Reached, failed CHECK. |
| + if (true) |
| + CHECK(!bool_expr()); |
| + } |
| + |
| + // The following four cases validate that the CHECK is correctly bound in an |
| + // 'if/else' statement. |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached if, successful else. |
| + if (false) |
| + CHECK(UnreachedBoolExpr()); |
| + else |
| + CHECK(bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Successful if, unreached else. |
| + if (true) |
| + CHECK(bool_expr()); |
| + else |
| + CHECK(UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Unreached if, failed else. |
| + if (false) |
| + CHECK(UnreachedBoolExpr()); |
| + else |
| + CHECK(!bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Failed if, unreached else. |
| + if (true) |
| + CHECK(!bool_expr()); |
| + else |
| + CHECK(UnreachedBoolExpr()); |
| + } |
| + |
| + // These cases validate that a CHECK may appear in a switch statement. |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + switch (2) { |
| + case 1: |
| + CHECK(UnreachedBoolExpr()); |
| + case 2: |
| + CHECK(bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + switch (2) { |
| + case 1: |
| + CHECK(UnreachedBoolExpr()); |
| + case 2: |
| + CHECK(!bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| +} |
| + |
| +// Test that DCHECK_EQ acts as a single statement in variety of syntactic |
| +// situations. |
| +TEST_F(LoggingTest, DCheckEqStatements) { |
| + // The next three blocks validate that the DCHECK_EQ is correctly bound to the |
| + // 'if' statement. |
| + { |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached DCHECK_EQ. |
| + if (false) |
| + DCHECK_EQ(false, UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Reached, successful DCHECK_EQ. |
| + if (true) |
| + DCHECK_EQ(true, bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Reached, failed DCHECK_EQ. |
| + if (true) |
| + DCHECK_EQ(false, bool_expr()); |
| + } |
| + |
| + // The following four cases validate that the DCHECK_EQ is correctly bound in |
| + // an 'if/else' statement. |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached if, successful else. |
| + if (false) |
| + DCHECK_EQ(false, UnreachedBoolExpr()); |
| + else |
| + DCHECK_EQ(true, bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Successful if, unreached else. |
| + if (true) |
| + DCHECK_EQ(true, bool_expr()); |
| + else |
| + DCHECK_EQ(false, UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Unreached if, failed else. |
| + if (false) |
| + DCHECK_EQ(false, UnreachedBoolExpr()); |
| + else |
| + DCHECK_EQ(false, bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Failed if, unreached else. |
| + if (true) |
| + DCHECK_EQ(false, bool_expr()); |
| + else |
| + DCHECK_EQ(false, UnreachedBoolExpr()); |
| + } |
| + |
| + // These cases validate that a DCHECK_EQ may appear in a switch statement. |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + switch (2) { |
| + case 1: |
| + DCHECK_EQ(false, UnreachedBoolExpr()); |
| + case 2: |
| + DCHECK_EQ(true, bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + switch (2) { |
| + case 1: |
| + DCHECK_EQ(false, UnreachedBoolExpr()); |
| + case 2: |
| + DCHECK_EQ(false, bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| +} |
| + |
| +// Test that CHECK_EQ acts as a single statement in variety of syntactic |
| +// situations. |
| +TEST_F(LoggingTest, CheckEqStatements) { |
| + // The next three blocks validate that the CHECK_EQ is correctly bound to the |
| + // 'if' statement. |
| + { |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached CHECK_EQ. |
| + if (false) |
| + CHECK_EQ(false, UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Reached, successful CHECK_EQ. |
| + if (true) |
| + CHECK_EQ(true, bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Reached, failed CHECK_EQ. |
| + if (true) |
| + CHECK_EQ(false, bool_expr()); |
| + } |
| + |
| + // The following four cases validate that the CHECK_EQ is correctly bound in |
| + // an 'if/else' statement. |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached if, successful else. |
| + if (false) |
| + CHECK_EQ(false, UnreachedBoolExpr()); |
| + else |
| + CHECK_EQ(true, bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Successful if, unreached else. |
| + if (true) |
| + CHECK_EQ(true, bool_expr()); |
| + else |
| + CHECK_EQ(false, UnreachedBoolExpr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Unreached if, failed else. |
| + if (false) |
| + CHECK_EQ(false, UnreachedBoolExpr()); |
| + else |
| + CHECK_EQ(false, bool_expr()); |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Failed if, unreached else. |
| + if (true) |
| + CHECK_EQ(false, bool_expr()); |
| + else |
| + CHECK_EQ(false, UnreachedBoolExpr()); |
| + } |
| + |
| + // These cases validate that a CHECK_EQ may appear in a switch statement. |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + switch (2) { |
| + case 1: |
| + CHECK_EQ(false, UnreachedBoolExpr()); |
| + case 2: |
| + CHECK_EQ(true, bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + switch (2) { |
| + case 1: |
| + CHECK_EQ(false, UnreachedBoolExpr()); |
| + case 2: |
| + CHECK_EQ(false, bool_expr()); |
| + default: |
| + break; |
| + } |
| + } |
| +} |
| + |
| +// Test that DLOG_IF acts as a single statement in variety of syntactic |
| +// situations. |
| +TEST_F(LoggingTest, DLogIfStatements) { |
| + // The next three blocks validate that the DLOG_IF is correctly bound to the |
| + // 'if' statement. |
| + { |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached DLOG_IF. |
| + if (false) |
| + DLOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Reached, negative DLOG_IF. |
| + if (true) |
| + DLOG_IF(FATAL, !bool_expr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Reached, positive DLOG_IF. |
| + if (true) |
| + DLOG_IF(FATAL, bool_expr()) << "message"; |
| + } |
| + |
| + // The following four cases validate that the DLOG_IF is correctly bound in an |
| + // 'if/else' statement. |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached if, negative else. |
| + if (false) |
| + DLOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + else |
| + DLOG_IF(FATAL, !bool_expr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Negative if, unreached else. |
| + if (true) |
| + DLOG_IF(FATAL, !bool_expr()) << "message"; |
| + else |
| + DLOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Unreached if, positive else. |
| + if (false) |
| + DLOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + else |
| + DLOG_IF(FATAL, bool_expr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + |
| + // Positive if, unreached else. |
| + if (true) |
| + DLOG_IF(FATAL, bool_expr()) << "message"; |
| + else |
| + DLOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + } |
| + |
| + // These cases validate that a DLOG_IF may appear in a switch statement. |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + switch (2) { |
| + case 1: |
| + DLOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + case 2: |
| + DLOG_IF(FATAL, !bool_expr()) << "message"; |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + { |
| + EvaluatedOnceIfDCheckIsOn bool_expr; |
| + ExpectOneLogIfDCheckIsOn expect_one_dlog; |
| + switch (2) { |
| + case 1: |
| + DLOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + case 2: |
| + DLOG_IF(FATAL, bool_expr()) << "message"; |
| + default: |
| + break; |
| + } |
| + } |
| +} |
| + |
| +// Test that LOG_IF acts as a single statement in variety of syntactic |
| +// situations. |
| +TEST_F(LoggingTest, LogIfStatements) { |
| + // The next three blocks validate that the LOG_IF is correctly bound to the |
| + // 'if' statement. |
| + { |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached LOG_IF. |
| + if (false) |
| + LOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Reached, negative LOG_IF. |
| + if (true) |
| + LOG_IF(FATAL, !bool_expr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Reached, positive LOG_IF. |
| + if (true) |
| + LOG_IF(FATAL, bool_expr()) << "message"; |
| + } |
| + |
| + // The following four cases validate that the LOG_IF is correctly bound in an |
| + // 'if/else' statement. |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Unreached if, negative else. |
| + if (false) |
| + LOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + else |
| + LOG_IF(FATAL, !bool_expr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + |
| + // Negative if, unreached else. |
| + if (true) |
| + LOG_IF(FATAL, !bool_expr()) << "message"; |
| + else |
| + LOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Unreached if, positive else. |
| + if (false) |
| + LOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + else |
| + LOG_IF(FATAL, bool_expr()) << "message"; |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + |
| + // Positive if, unreached else. |
| + if (true) |
| + LOG_IF(FATAL, bool_expr()) << "message"; |
| + else |
| + LOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + } |
| + |
| + // These cases validate that a LOG_IF may appear in a switch statement. |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectNoLogs expect_no_logs; |
| + switch (2) { |
| + case 1: |
| + LOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + case 2: |
| + LOG_IF(FATAL, !bool_expr()) << "message"; |
| + default: |
| + break; |
| + } |
| + } |
| + |
| + { |
| + EvaluatedOnce bool_expr; |
| + ExpectOneLog expect_one_log; |
| + switch (2) { |
| + case 1: |
| + LOG_IF(FATAL, UnreachedBoolExpr()) << "message"; |
| + case 2: |
| + LOG_IF(FATAL, bool_expr()) << "message"; |
| + default: |
| + break; |
| + } |
| + } |
| +} |
| + |
| // 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 |