summaryrefslogtreecommitdiffstats
path: root/net/test
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-25 20:31:10 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-25 20:31:10 +0000
commitbe8cff83b5fdd35792ff5612043972182fa9c67d (patch)
tree5d248e488e15fea31969878bc40c5ad5f72ba68f /net/test
parent8e89b03ada36070a5f22791ff51a23539b471798 (diff)
downloadchromium_src-be8cff83b5fdd35792ff5612043972182fa9c67d.zip
chromium_src-be8cff83b5fdd35792ff5612043972182fa9c67d.tar.gz
chromium_src-be8cff83b5fdd35792ff5612043972182fa9c67d.tar.bz2
Use EXPECT_DFATAL instead of EXPECT_DEBUG_DEATH in spdy_protocol_test.cc.
Switch the associated DCHECK to a LOG_IF(DFATAL). Move EXPECT_DFATAL, and friends, from net/quic/test_tools/ to net/test/. Merge internal change: 60170975 Review URL: https://codereview.chromium.org/134193004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247136 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/test')
-rw-r--r--net/test/gtest_util.h99
-rw-r--r--net/test/scoped_disable_exit_on_dfatal.cc33
-rw-r--r--net/test/scoped_disable_exit_on_dfatal.h39
-rw-r--r--net/test/scoped_mock_log.cc58
-rw-r--r--net/test/scoped_mock_log.h98
5 files changed, 327 insertions, 0 deletions
diff --git a/net/test/gtest_util.h b/net/test/gtest_util.h
new file mode 100644
index 0000000..14492c2
--- /dev/null
+++ b/net/test/gtest_util.h
@@ -0,0 +1,99 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Testing utilities that extend gtest.
+
+#ifndef NET_QUIC_TEST_TOOLS_GTEST_UTIL_H_
+#define NET_QUIC_TEST_TOOLS_GTEST_UTIL_H_
+
+#include "net/test/scoped_disable_exit_on_dfatal.h"
+#include "net/test/scoped_mock_log.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+// Internal implementation for the EXPECT_DFATAL and ASSERT_DFATAL
+// macros. Do not use this directly.
+#define GTEST_DFATAL_(statement, matcher, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (true) { \
+ ::net::test::ScopedMockLog gtest_log; \
+ ::net::test::ScopedDisableExitOnDFatal gtest_disable_exit; \
+ using ::testing::_; \
+ EXPECT_CALL(gtest_log, Log(_, _, _, _, _)) \
+ .WillRepeatedly(::testing::Return(false)); \
+ EXPECT_CALL(gtest_log, Log(logging::LOG_DFATAL, _, _, _, matcher)) \
+ .Times(::testing::AtLeast(1)) \
+ .WillOnce(::testing::Return(false)); \
+ gtest_log.StartCapturingLogs(); \
+ { statement; } \
+ gtest_log.StopCapturingLogs(); \
+ if (!testing::Mock::VerifyAndClear(&gtest_log)) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_dfatal_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_dfatal_, __LINE__): \
+ fail("")
+
+// The EXPECT_DFATAL and ASSERT_DFATAL macros are lightweight
+// alternatives to EXPECT_DEBUG_DEATH and ASSERT_DEBUG_DEATH. They
+// are appropriate for testing that your code logs a message at the
+// DFATAL level.
+//
+// Unlike EXPECT_DEBUG_DEATH and ASSERT_DEBUG_DEATH, these macros
+// execute the given statement in the current process, not a forked
+// one. This works because we disable exiting the program for
+// LOG(DFATAL). This makes the tests run more quickly.
+//
+// The _WITH() variants allow one to specify any matcher for the
+// DFATAL log message, whereas the other variants assume a regex.
+
+#define EXPECT_DFATAL_WITH(statement, matcher) \
+ GTEST_DFATAL_(statement, matcher, GTEST_NONFATAL_FAILURE_)
+
+#define ASSERT_DFATAL_WITH(statement, matcher) \
+ GTEST_DFATAL_(statement, matcher, GTEST_FATAL_FAILURE_)
+
+#define EXPECT_DFATAL(statement, regex) \
+ EXPECT_DFATAL_WITH(statement, ::testing::ContainsRegex(regex))
+
+#define ASSERT_DFATAL(statement, regex) \
+ ASSERT_DFATAL_WITH(statement, ::testing::ContainsRegex(regex))
+
+// The EXPECT_DEBUG_DFATAL and ASSERT_DEBUG_DFATAL macros are similar to
+// EXPECT_DFATAL and ASSERT_DFATAL. Use them in conjunction with DLOG(DFATAL)
+// or similar macros that produce no-op in opt build and DFATAL in dbg build.
+
+#ifndef NDEBUG
+
+#define EXPECT_DEBUG_DFATAL(statement, regex) \
+ EXPECT_DFATAL(statement, regex)
+#define ASSERT_DEBUG_DFATAL(statement, regex) \
+ ASSERT_DFATAL(statement, regex)
+
+#else // NDEBUG
+
+#define EXPECT_DEBUG_DFATAL(statement, regex) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (true) { \
+ (void)(regex); \
+ statement; \
+ } else \
+ GTEST_NONFATAL_FAILURE_("")
+#define ASSERT_DEBUG_DFATAL(statement, regex) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (true) { \
+ (void)(regex); \
+ statement; \
+ } else \
+ GTEST_NONFATAL_FAILURE_("")
+
+#endif // NDEBUG
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_GTEST_UTIL_H_
diff --git a/net/test/scoped_disable_exit_on_dfatal.cc b/net/test/scoped_disable_exit_on_dfatal.cc
new file mode 100644
index 0000000..f909126
--- /dev/null
+++ b/net/test/scoped_disable_exit_on_dfatal.cc
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/test/scoped_disable_exit_on_dfatal.h"
+
+#include "base/logging.h"
+
+namespace net {
+namespace test {
+
+// static
+ScopedDisableExitOnDFatal* ScopedDisableExitOnDFatal::g_instance_ = NULL;
+
+ScopedDisableExitOnDFatal::ScopedDisableExitOnDFatal() {
+ CHECK(!g_instance_);
+ g_instance_ = this;
+ logging::SetLogAssertHandler(LogAssertHandler);
+}
+
+ScopedDisableExitOnDFatal::~ScopedDisableExitOnDFatal() {
+ CHECK_EQ(g_instance_, this);
+ logging::SetLogAssertHandler(NULL);
+ g_instance_ = NULL;
+}
+
+// static
+void ScopedDisableExitOnDFatal::LogAssertHandler(const std::string& str) {
+ // Simply swallow the assert.
+}
+
+} // namespace test
+} // namespace net
diff --git a/net/test/scoped_disable_exit_on_dfatal.h b/net/test/scoped_disable_exit_on_dfatal.h
new file mode 100644
index 0000000..5df8ff7
--- /dev/null
+++ b/net/test/scoped_disable_exit_on_dfatal.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_TEST_TOOLS_SCOPED_DISABLE_EXIT_ON_DFATAL_H_
+#define NET_QUIC_TEST_TOOLS_SCOPED_DISABLE_EXIT_ON_DFATAL_H_
+
+#include "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+
+// The ScopedDisableExitOnDFatal class is used to disable exiting the
+// program when we encounter a LOG(DFATAL) within the current block.
+// After we leave the current block, the default behavior is
+// restored.
+class ScopedDisableExitOnDFatal {
+ public:
+ ScopedDisableExitOnDFatal();
+ ~ScopedDisableExitOnDFatal();
+
+ private:
+ // Currently active instance.
+ static ScopedDisableExitOnDFatal* g_instance_;
+
+ // Static function which is set as the logging assert handler.
+ // Called when there is a check failure.
+ static void LogAssertHandler(const std::string& msg);
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDisableExitOnDFatal);
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_SCOPED_DISABLE_EXIT_ON_DFATAL_H_
diff --git a/net/test/scoped_mock_log.cc b/net/test/scoped_mock_log.cc
new file mode 100644
index 0000000..3bc99cb
--- /dev/null
+++ b/net/test/scoped_mock_log.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/test/scoped_mock_log.h"
+
+#include "base/logging.h"
+
+namespace net {
+namespace test {
+
+// static
+ScopedMockLog* ScopedMockLog::g_instance_ = NULL;
+
+ScopedMockLog::ScopedMockLog() : is_capturing_logs_(false) {}
+
+ScopedMockLog::~ScopedMockLog() {
+ if (is_capturing_logs_) {
+ StopCapturingLogs();
+ }
+}
+
+void ScopedMockLog::StartCapturingLogs() {
+ // We don't use CHECK(), which can generate a new LOG message, and
+ // thus can confuse ScopedMockLog objects or other registered
+ // LogSinks.
+ RAW_CHECK(!is_capturing_logs_);
+ RAW_CHECK(!g_instance_);
+
+ is_capturing_logs_ = true;
+ g_instance_ = this;
+ previous_handler_ = logging::GetLogMessageHandler();
+ logging::SetLogMessageHandler(LogMessageHandler);
+}
+
+void ScopedMockLog::StopCapturingLogs() {
+ // We don't use CHECK(), which can generate a new LOG message, and
+ // thus can confuse ScopedMockLog objects or other registered
+ // LogSinks.
+ RAW_CHECK(is_capturing_logs_);
+ RAW_CHECK(g_instance_ == this);
+
+ is_capturing_logs_ = false;
+ logging::SetLogMessageHandler(previous_handler_);
+ g_instance_ = NULL;
+}
+
+// static
+bool ScopedMockLog::LogMessageHandler(int severity,
+ const char* file,
+ int line,
+ size_t message_start,
+ const std::string& str) {
+ return g_instance_->Log(severity, file, line, message_start, str);
+}
+
+} // namespace test
+} // namespace net
diff --git a/net/test/scoped_mock_log.h b/net/test/scoped_mock_log.h
new file mode 100644
index 0000000..e1edfcc
--- /dev/null
+++ b/net/test/scoped_mock_log.h
@@ -0,0 +1,98 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_TEST_TOOLS_SCOPED_MOCK_LOG_H_
+#define NET_QUIC_TEST_TOOLS_SCOPED_MOCK_LOG_H_
+
+#include "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+// A ScopedMockLog 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) {
+// ScopedMockLog 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 ScopedMockLog::Log(). You may call
+// RAW_LOG() instead.
+class ScopedMockLog {
+ public:
+ // Creates a ScopedMockLog 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).
+ ScopedMockLog();
+
+ // When the object is destructed, it stops intercepting logs.
+ ~ScopedMockLog();
+
+ // Starts log capturing if the object isn't already doing so.
+ // Otherwise crashes. Usually this method is called in the same
+ // thread that created this object. It is the user's responsibility
+ // to not call this method if another thread may be calling it or
+ // StopCapturingLogs() at the same time.
+ void StartCapturingLogs();
+
+ // Stops log capturing if the object is capturing logs. Otherwise
+ // crashes. Usually this method is called in the same thread that
+ // created this object. It is the user's responsibility to not call
+ // this method if another thread may be calling it or
+ // StartCapturingLogs() at the same time.
+ void StopCapturingLogs();
+
+ // Sets the Log Message Handler that gets passed every log message before
+ // it's sent to other log destinations (if any).
+ // Returns 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 scoped mock log.
+ static ScopedMockLog* g_instance_;
+
+ // 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 ScopedMockLog is destroyed.
+ logging::LogMessageHandlerFunction previous_handler_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_SCOPED_MOCK_LOG_H_