| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_TEST_MOCK_LOG_H_ |
| #define BASE_TEST_MOCK_LOG_H_ |
| |
| #include <stddef.h> |
| |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "base/synchronization/lock.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| |
| namespace base { |
| namespace test { |
| |
| // A MockLog object intercepts LOG() messages issued during its lifespan. Using |
| // this together with gMock, it's very easy to test how a piece of code calls |
| // LOG(). The typical usage: |
| // |
| // TEST(FooTest, LogsCorrectly) { |
| // MockLog log; |
| // |
| // // We expect the WARNING "Something bad!" exactly twice. |
| // EXPECT_CALL(log, Log(WARNING, _, "Something bad!")) |
| // .Times(2); |
| // |
| // // We allow foo.cc to call LOG(INFO) any number of times. |
| // EXPECT_CALL(log, Log(INFO, HasSubstr("/foo.cc"), _)) |
| // .Times(AnyNumber()); |
| // |
| // log.StartCapturingLogs(); // Call this after done setting expectations. |
| // Foo(); // Exercises the code under test. |
| // } |
| // |
| // CAVEAT: base/logging does not allow a thread to call LOG() again when it's |
| // already inside a LOG() call. Doing so will cause a deadlock. Therefore, |
| // it's the user's responsibility to not call LOG() in an action triggered by |
| // MockLog::Log(). You may call RAW_LOG() instead. |
| class MockLog { |
| public: |
| // Creates a MockLog object that is not capturing logs. If it were to start |
| // to capture logs, it could be a problem if some other threads already exist |
| // and are logging, as the user hasn't had a chance to set up expectation on |
| // this object yet (calling a mock method before setting the expectation is |
| // UNDEFINED behavior). |
| MockLog(); |
| |
| MockLog(const MockLog&) = delete; |
| MockLog& operator=(const MockLog&) = delete; |
| |
| // When the object is destructed, it stops intercepting logs. |
| ~MockLog(); |
| |
| // Starts log capturing if the object isn't already doing so. |
| // Otherwise crashes. |
| void StartCapturingLogs(); |
| |
| // Stops log capturing if the object is capturing logs. Otherwise crashes. |
| void StopCapturingLogs(); |
| |
| // Log method is invoked for every log message before it's sent to other log |
| // destinations (if any). The method should return true to signal that it |
| // handled the message and the message should not be sent to other log |
| // destinations. |
| MOCK_METHOD5(Log, |
| bool(int severity, |
| const char* file, |
| int line, |
| size_t message_start, |
| const std::string& str)); |
| |
| private: |
| // The currently active mock log. |
| static MockLog* g_instance_; |
| |
| // Lock protecting access to g_instance_. |
| static Lock g_lock; |
| |
| // Static function which is set as the logging message handler. |
| // Called once for each message. |
| static bool LogMessageHandler(int severity, |
| const char* file, |
| int line, |
| size_t message_start, |
| const std::string& str); |
| |
| // True if this object is currently capturing logs. |
| bool is_capturing_logs_; |
| |
| // The previous handler to restore when the MockLog is destroyed. |
| logging::LogMessageHandlerFunction previous_handler_; |
| }; |
| |
| } // namespace test |
| } // namespace base |
| |
| #endif // BASE_TEST_MOCK_LOG_H_ |