1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_QUIC_TEST_TOOLS_SCOPED_MOCK_LOG_H_
6#define NET_QUIC_TEST_TOOLS_SCOPED_MOCK_LOG_H_
7
8#include "base/logging.h"
9#include "testing/gmock/include/gmock/gmock.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace net {
13namespace test {
14
15// A ScopedMockLog object intercepts LOG() messages issued during its
16// lifespan.  Using this together with gMock, it's very easy to test
17// how a piece of code calls LOG().  The typical usage:
18//
19//   TEST(FooTest, LogsCorrectly) {
20//     ScopedMockLog log;
21//
22//     // We expect the WARNING "Something bad!" exactly twice.
23//     EXPECT_CALL(log, Log(WARNING, _, "Something bad!"))
24//         .Times(2);
25//
26//     // We allow foo.cc to call LOG(INFO) any number of times.
27//     EXPECT_CALL(log, Log(INFO, HasSubstr("/foo.cc"), _))
28//         .Times(AnyNumber());
29//
30//     log.StartCapturingLogs();  // Call this after done setting expectations.
31//     Foo();  // Exercises the code under test.
32//   }
33//
34// CAVEAT: base/logging does not allow a thread to call LOG() again
35// when it's already inside a LOG() call.  Doing so will cause a
36// deadlock.  Therefore, it's the user's responsibility to not call
37// LOG() in an action triggered by ScopedMockLog::Log().  You may call
38// RAW_LOG() instead.
39class ScopedMockLog {
40 public:
41  // Creates a ScopedMockLog object that is not capturing logs.
42  // If it were to start to capture logs, it could be a problem if
43  // some other threads already exist and are logging, as the user
44  // hasn't had a chance to set up expectation on this object yet
45  // (calling a mock method before setting the expectation is
46  // UNDEFINED behavior).
47  ScopedMockLog();
48
49  // When the object is destructed, it stops intercepting logs.
50  ~ScopedMockLog();
51
52  // Starts log capturing if the object isn't already doing so.
53  // Otherwise crashes.  Usually this method is called in the same
54  // thread that created this object.  It is the user's responsibility
55  // to not call this method if another thread may be calling it or
56  // StopCapturingLogs() at the same time.
57  void StartCapturingLogs();
58
59  // Stops log capturing if the object is capturing logs.  Otherwise
60  // crashes.  Usually this method is called in the same thread that
61  // created this object.  It is the user's responsibility to not call
62  // this method if another thread may be calling it or
63  // StartCapturingLogs() at the same time.
64  void StopCapturingLogs();
65
66  // Sets the Log Message Handler that gets passed every log message before
67  // it's sent to other log destinations (if any).
68  // Returns true to signal that it handled the message and the message
69  // should not be sent to other log destinations.
70  MOCK_METHOD5(Log, bool(int severity,
71                         const char* file,
72                         int line,
73                         size_t message_start,
74                         const std::string& str));
75
76 private:
77  // The currently active scoped mock log.
78  static ScopedMockLog* g_instance_;
79
80  // Static function which is set as the logging message handler.
81  // Called once for each message.
82  static bool LogMessageHandler(int severity,
83                                const char* file,
84                                int line,
85                                size_t message_start,
86                                const std::string& str);
87
88  // True if this object is currently capturing logs.
89  bool is_capturing_logs_;
90
91  // The previous handler to restore when the ScopedMockLog is destroyed.
92  logging::LogMessageHandlerFunction previous_handler_;
93};
94
95}  // namespace test
96}  // namespace net
97
98#endif  // NET_QUIC_TEST_TOOLS_SCOPED_MOCK_LOG_H_
99