diff --git a/test/util/test_util.h b/test/util/test_util.h index 7421c0e0c..3ad324ebe 100644 --- a/test/util/test_util.h +++ b/test/util/test_util.h @@ -292,6 +292,20 @@ inline uint64_t ms_elapsed(const struct timespec& begin, namespace internal { +// RAII class to restore errno. Used because malloc/new are not guaranteed to +// preserve errno. +class ErrnoRestorer { + public: + ErrnoRestorer() : saved_errno_(errno) {} + ~ErrnoRestorer() { errno = saved_errno_; } + + ErrnoRestorer(const ErrnoRestorer&) = delete; + ErrnoRestorer& operator=(const ErrnoRestorer&) = delete; + + private: + int saved_errno_; +}; + template class ElementOfMatcher { public: @@ -337,6 +351,8 @@ class SyscallSuccessMatcher { template operator ::testing::Matcher() const { + ErrnoRestorer errno_restorer; + // E is one of three things: // - T, or a type losslessly and implicitly convertible to T. // - A monomorphic Matcher. @@ -393,6 +409,7 @@ class AnySuccessValueMatcher { public: template operator ::testing::Matcher() const { + ErrnoRestorer errno_restorer; return ::testing::MakeMatcher(new Impl()); } @@ -473,6 +490,7 @@ class SpecificErrnoMatcher : public ::testing::MatcherInterface { }; inline ::testing::Matcher SpecificErrno(int const expected) { + ErrnoRestorer errno_restorer; return ::testing::MakeMatcher(new SpecificErrnoMatcher(expected)); }