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 |