Make sure IsATTY does not clobber errno.
Exposition of the problem: > cat main.cpp TEST(errnoTest, errnoTest) { ASSERT_EQ(errno, 0); } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } Compiled with gcc 10 like this: > g++ -pthread -o runtest main.cpp -Wl,-Bstatic -lgtest -Wl,-Bdynamic Before patch: > ./runtest [==========] Running 1 test from 1 test suite. [----------] Global test environment set-up. [----------] 1 test from errnoTest [ RUN ] errnoTest.errnoTest [ OK ] errnoTest.errnoTest (0 ms) [----------] 1 test from errnoTest (0 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test suite ran. (0 ms total) [ PASSED ] 1 test. (output is colored, I run this inside an interactive terminal). > ./runtest | cat [==========] Running 1 test from 1 test suite. [----------] Global test environment set-up. [----------] 1 test from errnoTest [ RUN ] errnoTest.errnoTest main.cpp:5: Failure Expected equality of these values: (*__errno_location ()) Which is: 25 0 [ FAILED ] errnoTest.errnoTest (0 ms) [----------] 1 test from errnoTest (0 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test suite ran. (0 ms total) [ PASSED ] 0 tests. [ FAILED ] 1 test, listed below: [ FAILED ] errnoTest.errnoTest 1 FAILED TEST (output is not colored, since IsTTY return false, because of the pipe, however it also clobbered errno for the tests). After the patch, both cases are working fine: > ./runtest [==========] Running 1 test from 1 test suite. [----------] Global test environment set-up. [----------] 1 test from errnoTest [ RUN ] errnoTest.errnoTest [ OK ] errnoTest.errnoTest (0 ms) [----------] 1 test from errnoTest (0 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test suite ran. (0 ms total) [ PASSED ] 1 test. > ./runtest | cat [==========] Running 1 test from 1 test suite. [----------] Global test environment set-up. [----------] 1 test from errnoTest [ RUN ] errnoTest.errnoTest [ OK ] errnoTest.errnoTest (0 ms) [----------] 1 test from errnoTest (0 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test suite ran. (0 ms total) [ PASSED ] 1 test.
This commit is contained in:
parent
e588eb1ff9
commit
a1b0173df9
|
@ -252,6 +252,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
@ -1960,16 +1961,16 @@ namespace posix {
|
|||
typedef struct _stat StatStruct;
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
inline int IsATTY(int fd) { return isatty(fd); }
|
||||
inline int DoIsATTY(int fd) { return isatty(fd); }
|
||||
inline int StrCaseCmp(const char* s1, const char* s2) {
|
||||
return stricmp(s1, s2);
|
||||
}
|
||||
inline char* StrDup(const char* src) { return strdup(src); }
|
||||
# else // !__BORLANDC__
|
||||
# if GTEST_OS_WINDOWS_MOBILE
|
||||
inline int IsATTY(int /* fd */) { return 0; }
|
||||
inline int DoIsATTY(int /* fd */) { return 0; }
|
||||
# else
|
||||
inline int IsATTY(int fd) { return _isatty(fd); }
|
||||
inline int DoIsATTY(int fd) { return _isatty(fd); }
|
||||
# endif // GTEST_OS_WINDOWS_MOBILE
|
||||
inline int StrCaseCmp(const char* s1, const char* s2) {
|
||||
return _stricmp(s1, s2);
|
||||
|
@ -1994,7 +1995,7 @@ inline bool IsDir(const StatStruct& st) {
|
|||
typedef struct stat StatStruct;
|
||||
|
||||
inline int FileNo(FILE* file) { return fileno(file); }
|
||||
inline int IsATTY(int fd) { return isatty(fd); }
|
||||
inline int DoIsATTY(int fd) { return isatty(fd); }
|
||||
inline int Stat(const char* path, StatStruct* buf) {
|
||||
// stat function not implemented on ESP8266
|
||||
return 0;
|
||||
|
@ -2011,7 +2012,7 @@ inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
|
|||
typedef struct stat StatStruct;
|
||||
|
||||
inline int FileNo(FILE* file) { return fileno(file); }
|
||||
inline int IsATTY(int fd) { return isatty(fd); }
|
||||
inline int DoIsATTY(int fd) { return isatty(fd); }
|
||||
inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
|
||||
inline int StrCaseCmp(const char* s1, const char* s2) {
|
||||
return strcasecmp(s1, s2);
|
||||
|
@ -2022,6 +2023,18 @@ inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
|
|||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
inline int IsATTY(int fd)
|
||||
{
|
||||
// DoIsATTY might change errno (for example ENOTTY in case you redirect stdout
|
||||
// to a file on Linux), which is unexpected, so save the previous value, and
|
||||
// restore it after the call.
|
||||
int savedErrno = errno;
|
||||
int isAttyValue = DoIsATTY(fd);
|
||||
errno = savedErrno;
|
||||
|
||||
return isAttyValue;
|
||||
}
|
||||
|
||||
// Functions deprecated by MSVC 8.0.
|
||||
|
||||
GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
|
||||
|
|
Loading…
Reference in New Issue
Block a user