Commit 63e1deef authored by Greg Thompson's avatar Greg Thompson Committed by Commit Bot

Teach Google Test how to emit stack traces.

This CL provides an OsStackTraceGetterInterface implementation for
Google Test that uses Chromium's base::debug. This allows Google Test to
emit stack traces to make debugging test failures a bit easier. As a
result, failures that once looked like the following will now include
stack traces:

[ RUN      ] UpgradeDetectorImplTest.TestPeriodChanges
unknown file: error: Uninteresting mock function call - returning directly.
    Function call: OnUpgradeRecommended()
[  FAILED  ] UpgradeDetectorImplTest.TestPeriodChanges (3 ms)

BUG=none
R=dpranke@chromium.org

Change-Id: I992d807cc654104d0bad461fda8cb82c86e6e9f8
Reviewed-on: https://chromium-review.googlesource.com/1009947
Commit-Queue: Greg Thompson <grt@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551083}
parent 1f4159ae
...@@ -23,7 +23,10 @@ config("gtest_config") { ...@@ -23,7 +23,10 @@ config("gtest_config") {
] ]
# Gtest headers need to be able to find themselves. # Gtest headers need to be able to find themselves.
include_dirs = [ "src/googletest/include" ] include_dirs = [
"custom",
"src/googletest/include",
]
if (is_win) { if (is_win) {
cflags = [ "/wd4800" ] # Unused variable warning. cflags = [ "/wd4800" ] # Unused variable warning.
...@@ -43,6 +46,9 @@ config("gmock_config") { ...@@ -43,6 +46,9 @@ config("gmock_config") {
source_set("gtest") { source_set("gtest") {
testonly = true testonly = true
sources = [ sources = [
"custom/gtest/internal/custom/gtest.h",
"custom/gtest/internal/custom/stack_trace_getter.cc",
"custom/gtest/internal/custom/stack_trace_getter.h",
"src/googletest/include/gtest/gtest-death-test.h", "src/googletest/include/gtest/gtest-death-test.h",
"src/googletest/include/gtest/gtest-message.h", "src/googletest/include/gtest/gtest-message.h",
"src/googletest/include/gtest/gtest-param-test.h", "src/googletest/include/gtest/gtest-param-test.h",
...@@ -81,6 +87,17 @@ source_set("gtest") { ...@@ -81,6 +87,17 @@ source_set("gtest") {
configs -= [ "//build/config/compiler:chromium_code" ] configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ]
if (is_nacl) {
sources -= [
"custom/gtest/internal/custom/stack_trace_getter.cc",
"custom/gtest/internal/custom/stack_trace_getter.h",
]
} else {
deps = [
"//base",
]
}
} }
# Do NOT depend on this directly. Use //testing/gtest:gtest_main instead. # Do NOT depend on this directly. Use //testing/gtest:gtest_main instead.
......
# This directory contains Google Test glue that depends on //base.
include_rules = [
'+base',
'+build',
]
// Copyright 2018 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 THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_H_
#define THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_H_
#include "build/build_config.h"
#if !defined(OS_NACL)
#include "third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h"
// Tell Google Test to use a stack trace getter based on Chromium's
// base::debug::StackTrace.
#define GTEST_OS_STACK_TRACE_GETTER_ StackTraceGetter
#endif // defined(OS_NACL)
#endif // THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_H_
// Copyright 2018 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 "third_party/googletest/custom/gtest/internal/custom/stack_trace_getter.h"
#include "base/debug/stack_trace.h"
#include "base/format_macros.h"
namespace {
// The number of frames on the top of the stack to ignore in UponLeavingGTest.
// This may vary from build to build and platform to platform. On Windows
// release builds at the time of writing, the top two frames should be skipped:
// base::debug::StackTrace::StackTrace
// StackTraceGetter::UponLeavingGTest
enum : size_t { kDepartureSkipFrames = 2 };
} // namespace
std::string StackTraceGetter::CurrentStackTrace(int max_depth, int skip_count) {
base::debug::StackTrace stack_trace;
size_t frame_count = 0;
const void* const* addresses = stack_trace.Addresses(&frame_count);
// Drop the frames at the tail that were present the last time gtest was left.
if (frame_count_upon_leaving_gtest_ &&
frame_count > frame_count_upon_leaving_gtest_) {
frame_count -= frame_count_upon_leaving_gtest_;
}
// Ignore frames to skip.
if (skip_count >= 0 && static_cast<size_t>(skip_count) < frame_count) {
frame_count -= skip_count;
addresses += skip_count;
}
// Only return as many as requested.
if (max_depth >= 0 && static_cast<size_t>(max_depth) < frame_count)
frame_count = static_cast<size_t>(max_depth);
return base::debug::StackTrace(addresses, frame_count).ToString();
}
void StackTraceGetter::UponLeavingGTest() {
// Remember how deep the stack is as gtest is left.
base::debug::StackTrace().Addresses(&frame_count_upon_leaving_gtest_);
if (frame_count_upon_leaving_gtest_ > kDepartureSkipFrames)
frame_count_upon_leaving_gtest_ -= kDepartureSkipFrames;
}
// Copyright 2018 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 THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_
#define THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_
#include <stddef.h>
#include "third_party/googletest/src/googletest/src/gtest-internal-inl.h"
// An implementation of Google Test's OsStackTraceGetterInterface that uses
// Chromium's base::debug::StackTrace to obtain stringified stack traces.
class StackTraceGetter
: public ::testing::internal::OsStackTraceGetterInterface {
public:
StackTraceGetter() = default;
~StackTraceGetter() override = default;
StackTraceGetter(const StackTraceGetter&) = delete;
StackTraceGetter& operator=(const StackTraceGetter&) = delete;
// ::testing::internal::OsStackTraceGetterInterface:
std::string CurrentStackTrace(int max_depth, int skip_count) override;
void UponLeavingGTest() override;
private:
size_t frame_count_upon_leaving_gtest_ = 0;
};
#endif // THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_STACK_TRACE_GETTER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment