Split OsStackTraceGetter into AbslStackTraceGetter + NoopStackTraceGetter

The OsStackTraceGetter class does different things depending on whether
GTEST_HAS_ABSL is set. I want to add another implementation of
OsStackTraceGetter, and I think it's ugly if my new implementation
litters OsStackTraceGetter with more #if-s.

Split OsStackTraceGetter into two different classes:

* AbslStackTraceGetter, which is only defined if GTEST_HAS_ABSL is set.
  This class behaves the same as OsStackTraceGetter currently behaves.
* NoopStackTraceGetter, which is always defined. This class behaves the
  same as OsStackTraceGetter currently behaves if GTEST_HAS_ABSL is not
  set.

After this refactor, it is easier to add new OsStackTraceGetter
backend classes.
This commit is contained in:
Matthew Glazar 2023-08-09 20:21:00 -07:00
parent 89b25572db
commit 8aaea6c092
2 changed files with 39 additions and 22 deletions

View file

@ -433,16 +433,16 @@ class OsStackTraceGetterInterface {
delete;
};
#ifdef GTEST_HAS_ABSL
// A working implementation of the OsStackTraceGetterInterface interface.
class OsStackTraceGetter : public OsStackTraceGetterInterface {
class AbslStackTraceGetter : public OsStackTraceGetterInterface {
public:
OsStackTraceGetter() = default;
AbslStackTraceGetter() = default;
std::string CurrentStackTrace(int max_depth, int skip_count) override;
void UponLeavingGTest() override;
private:
#ifdef GTEST_HAS_ABSL
Mutex mutex_; // Protects all internal state.
// We save the stack frame below the frame that calls user code.
@ -450,10 +450,20 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface {
// the user code changes between the call to UponLeavingGTest()
// and any calls to the stack trace code from within the user code.
void* caller_frame_ = nullptr;
AbslStackTraceGetter(const AbslStackTraceGetter&) = delete;
AbslStackTraceGetter& operator=(const AbslStackTraceGetter&) = delete;
};
#endif // GTEST_HAS_ABSL
OsStackTraceGetter(const OsStackTraceGetter&) = delete;
OsStackTraceGetter& operator=(const OsStackTraceGetter&) = delete;
// An implementation of OsStackTraceGetterInterface which returns no
// stack trace.
class NoopStackTraceGetter : public OsStackTraceGetterInterface {
public:
NoopStackTraceGetter() = default;
std::string CurrentStackTrace(int max_depth, int skip_count) override;
void UponLeavingGTest() override;
};
// Information about a Google Test trace point.
@ -622,8 +632,8 @@ class GTEST_API_ UnitTestImpl {
void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
// Returns the current OS stack trace getter if it is not NULL;
// otherwise, creates an OsStackTraceGetter, makes it the current
// getter, and returns it.
// otherwise, creates an OsStackTraceGetterInterface, makes it the
// current getter, and returns it.
OsStackTraceGetterInterface* os_stack_trace_getter();
// Returns the current OS stack trace as an std::string.
@ -922,9 +932,9 @@ class GTEST_API_ UnitTestImpl {
TestEventListeners listeners_;
// The OS stack trace getter. Will be deleted when the UnitTest
// object is destructed. By default, an OsStackTraceGetter is used,
// but the user can set this field to use a custom getter if that is
// desired.
// object is destructed. By default, an OsStackTraceGetterInterface
// is created when os_stack_trace_getter is first called, but the user
// can set this field to use a custom getter if that is desired.
OsStackTraceGetterInterface* os_stack_trace_getter_;
// True if and only if PostFlagParsingInit() has been called.

View file

@ -4968,9 +4968,9 @@ void StreamingListener::SocketWriter::MakeConnection() {
const char* const OsStackTraceGetterInterface::kElidedFramesMarker =
"... " GTEST_NAME_ " internal frames ...";
std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
GTEST_LOCK_EXCLUDED_(mutex_) {
#ifdef GTEST_HAS_ABSL
std::string AbslStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
GTEST_LOCK_EXCLUDED_(mutex_) {
std::string result;
if (max_depth <= 0) {
@ -5010,16 +5010,11 @@ std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
}
return result;
#else // !GTEST_HAS_ABSL
static_cast<void>(max_depth);
static_cast<void>(skip_count);
return "";
#endif // GTEST_HAS_ABSL
}
#endif // GTEST_HAS_ABSL
void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
#ifdef GTEST_HAS_ABSL
void AbslStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
void* caller_frame = nullptr;
if (absl::GetStackTrace(&caller_frame, 1, 3) <= 0) {
caller_frame = nullptr;
@ -5027,7 +5022,17 @@ void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
MutexLock lock(&mutex_);
caller_frame_ = caller_frame;
}
#endif // GTEST_HAS_ABSL
std::string NoopStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count) {
static_cast<void>(max_depth);
static_cast<void>(skip_count);
return "";
}
void NoopStackTraceGetter::UponLeavingGTest() {
// Do nothing.
}
#ifdef GTEST_HAS_DEATH_TEST
@ -6233,14 +6238,16 @@ void UnitTestImpl::set_os_stack_trace_getter(
}
// Returns the current OS stack trace getter if it is not NULL;
// otherwise, creates an OsStackTraceGetter, makes it the current
// getter, and returns it.
// otherwise, creates an OsStackTraceGetterInterface, makes it the
// current getter, and returns it.
OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
if (os_stack_trace_getter_ == nullptr) {
#ifdef GTEST_OS_STACK_TRACE_GETTER_
os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_;
#elif defined(GTEST_HAS_ABSL)
os_stack_trace_getter_ = new AbslStackTraceGetter;
#else
os_stack_trace_getter_ = new OsStackTraceGetter;
os_stack_trace_getter_ = new NoopStackTraceGetter;
#endif // GTEST_OS_STACK_TRACE_GETTER_
}