diff options
Diffstat (limited to 'googletest/src/gtest-port.cc')
-rw-r--r-- | googletest/src/gtest-port.cc | 144 |
1 files changed, 112 insertions, 32 deletions
diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc index 950c16b..9024f03 100644 --- a/googletest/src/gtest-port.cc +++ b/googletest/src/gtest-port.cc @@ -55,6 +55,14 @@ # include <mach/vm_map.h> #endif // GTEST_OS_MAC +#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ + GTEST_OS_NETBSD || GTEST_OS_OPENBSD +# include <sys/sysctl.h> +# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD +# include <sys/user.h> +# endif +#endif + #if GTEST_OS_QNX # include <devctl.h> # include <fcntl.h> @@ -109,7 +117,7 @@ T ReadProcFileField(const std::string& filename, int field) { size_t GetThreadCount() { const std::string filename = (Message() << "/proc/" << getpid() << "/stat").GetString(); - return ReadProcFileField<int>(filename, 19); + return ReadProcFileField<size_t>(filename, 19); } #elif GTEST_OS_MAC @@ -131,6 +139,81 @@ size_t GetThreadCount() { } } +#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ + GTEST_OS_NETBSD + +#if GTEST_OS_NETBSD +#undef KERN_PROC +#define KERN_PROC KERN_PROC2 +#define kinfo_proc kinfo_proc2 +#endif + +#if GTEST_OS_DRAGONFLY +#define KP_NLWP(kp) (kp.kp_nthreads) +#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD +#define KP_NLWP(kp) (kp.ki_numthreads) +#elif GTEST_OS_NETBSD +#define KP_NLWP(kp) (kp.p_nlwps) +#endif + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + int mib[] = { + CTL_KERN, + KERN_PROC, + KERN_PROC_PID, + getpid(), +#if GTEST_OS_NETBSD + sizeof(struct kinfo_proc), + 1, +#endif + }; + u_int miblen = sizeof(mib) / sizeof(mib[0]); + struct kinfo_proc info; + size_t size = sizeof(info); + if (sysctl(mib, miblen, &info, &size, NULL, 0)) { + return 0; + } + return static_cast<size_t>(KP_NLWP(info)); +} +#elif GTEST_OS_OPENBSD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + int mib[] = { + CTL_KERN, + KERN_PROC, + KERN_PROC_PID | KERN_PROC_SHOW_THREADS, + getpid(), + sizeof(struct kinfo_proc), + 0, + }; + u_int miblen = sizeof(mib) / sizeof(mib[0]); + + // get number of structs + size_t size; + if (sysctl(mib, miblen, NULL, &size, NULL, 0)) { + return 0; + } + mib[5] = size / mib[4]; + + // populate array of structs + struct kinfo_proc info[mib[5]]; + if (sysctl(mib, miblen, &info, &size, NULL, 0)) { + return 0; + } + + // exclude empty members + int nthreads = 0; + for (int i = 0; i < size / mib[4]; i++) { + if (info[i].p_tid != -1) + nthreads++; + } + return nthreads; +} + #elif GTEST_OS_QNX // Returns the number of threads running in the process, or 0 to indicate that @@ -196,7 +279,7 @@ size_t GetThreadCount() { #if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS void SleepMilliseconds(int n) { - ::Sleep(n); + ::Sleep(static_cast<DWORD>(n)); } AutoHandle::AutoHandle() @@ -265,9 +348,6 @@ Mutex::Mutex() Mutex::~Mutex() { // Static mutexes are leaked intentionally. It is not thread-safe to try // to clean them up. - // FIXME: Switch to Slim Reader/Writer (SRW) Locks, which requires - // nothing to clean it up but is available only on Vista and later. - // https://docs.microsoft.com/en-us/windows/desktop/Sync/slim-reader-writer--srw--locks if (type_ == kDynamic) { ::DeleteCriticalSection(critical_section_); delete critical_section_; @@ -300,6 +380,7 @@ void Mutex::AssertHeld() { namespace { +#ifdef _MSC_VER // Use the RAII idiom to flag mem allocs that are intentionally never // deallocated. The motivation is to silence the false positive mem leaks // that are reported by the debug version of MS's CRT which can only detect @@ -312,19 +393,15 @@ class MemoryIsNotDeallocated { public: MemoryIsNotDeallocated() : old_crtdbg_flag_(0) { -#ifdef _MSC_VER old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT // doesn't report mem leak if there's no matching deallocation. _CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF); -#endif // _MSC_VER } ~MemoryIsNotDeallocated() { -#ifdef _MSC_VER // Restore the original _CRTDBG_ALLOC_MEM_DF flag _CrtSetDbgFlag(old_crtdbg_flag_); -#endif // _MSC_VER } private: @@ -332,6 +409,7 @@ class MemoryIsNotDeallocated GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated); }; +#endif // _MSC_VER } // namespace @@ -347,7 +425,9 @@ void Mutex::ThreadSafeLazyInit() { owner_thread_id_ = 0; { // Use RAII to flag that following mem alloc is never deallocated. +#ifdef _MSC_VER MemoryIsNotDeallocated memory_is_not_deallocated; +#endif // _MSC_VER critical_section_ = new CRITICAL_SECTION; } ::InitializeCriticalSection(critical_section_); @@ -388,7 +468,6 @@ class ThreadWithParamSupport : public ThreadWithParamBase { Notification* thread_can_start) { ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start); DWORD thread_id; - // FIXME: Consider to use _beginthreadex instead. HANDLE thread_handle = ::CreateThread( nullptr, // Default security. 0, // Default stack size. @@ -591,7 +670,9 @@ class ThreadLocalRegistryImpl { // Returns map of thread local instances. static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() { mutex_.AssertHeld(); +#ifdef _MSC_VER MemoryIsNotDeallocated memory_is_not_deallocated; +#endif // _MSC_VER static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals(); return map; } @@ -634,7 +715,7 @@ RE::~RE() { free(const_cast<char*>(pattern_)); } -// Returns true iff regular expression re matches the entire str. +// Returns true if regular expression re matches the entire str. bool RE::FullMatch(const char* str, const RE& re) { if (!re.is_valid_) return false; @@ -642,7 +723,7 @@ bool RE::FullMatch(const char* str, const RE& re) { return regexec(&re.full_regex_, str, 1, &match, 0) == 0; } -// Returns true iff regular expression re matches a substring of str +// Returns true if regular expression re matches a substring of str // (including str itself). bool RE::PartialMatch(const char* str, const RE& re) { if (!re.is_valid_) return false; @@ -683,13 +764,13 @@ void RE::Init(const char* regex) { #elif GTEST_USES_SIMPLE_RE -// Returns true iff ch appears anywhere in str (excluding the +// Returns true if ch appears anywhere in str (excluding the // terminating '\0' character). bool IsInSet(char ch, const char* str) { return ch != '\0' && strchr(str, ch) != nullptr; } -// Returns true iff ch belongs to the given classification. Unlike +// Returns true if ch belongs to the given classification. Unlike // similar functions in <ctype.h>, these aren't affected by the // current locale. bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } @@ -703,12 +784,12 @@ bool IsAsciiWordChar(char ch) { ('0' <= ch && ch <= '9') || ch == '_'; } -// Returns true iff "\\c" is a supported escape sequence. +// Returns true if "\\c" is a supported escape sequence. bool IsValidEscape(char c) { return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); } -// Returns true iff the given atom (specified by escaped and pattern) +// Returns true if the given atom (specified by escaped and pattern) // matches ch. The result is undefined if the atom is invalid. bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { if (escaped) { // "\\p" where p is pattern_char. @@ -741,16 +822,13 @@ static std::string FormatRegexSyntaxError(const char* regex, int index) { // otherwise returns true. bool ValidateRegex(const char* regex) { if (regex == nullptr) { - // FIXME: fix the source file location in the - // assertion failures to match where the regex is used in user - // code. ADD_FAILURE() << "NULL is not a valid simple regular expression."; return false; } bool is_valid = true; - // True iff ?, *, or + can follow the previous atom. + // True if ?, *, or + can follow the previous atom. bool prev_repeatable = false; for (int i = 0; regex[i]; i++) { if (regex[i] == '\\') { // An escape sequence @@ -826,7 +904,7 @@ bool MatchRepetitionAndRegexAtHead( return false; } -// Returns true iff regex matches a prefix of str. regex must be a +// Returns true if regex matches a prefix of str. regex must be a // valid simple regular expression and not start with "^", or the // result is undefined. bool MatchRegexAtHead(const char* regex, const char* str) { @@ -857,7 +935,7 @@ bool MatchRegexAtHead(const char* regex, const char* str) { } } -// Returns true iff regex matches any substring of str. regex must be +// Returns true if regex matches any substring of str. regex must be // a valid simple regular expression, or the result is undefined. // // The algorithm is recursive, but the recursion depth doesn't exceed @@ -886,12 +964,12 @@ RE::~RE() { free(const_cast<char*>(full_pattern_)); } -// Returns true iff regular expression re matches the entire str. +// Returns true if regular expression re matches the entire str. bool RE::FullMatch(const char* str, const RE& re) { return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); } -// Returns true iff regular expression re matches a substring of str +// Returns true if regular expression re matches a substring of str // (including str itself). bool RE::PartialMatch(const char* str, const RE& re) { return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); @@ -1035,6 +1113,11 @@ class CapturedStream { char name_template[] = "/tmp/captured_stream.XXXXXX"; # endif // GTEST_OS_LINUX_ANDROID const int captured_fd = mkstemp(name_template); + if (captured_fd == -1) { + GTEST_LOG_(WARNING) + << "Failed to create tmp file " << name_template + << " for test; does the test have access to the /tmp directory?"; + } filename_ = name_template; # endif // GTEST_OS_WINDOWS fflush(nullptr); @@ -1056,6 +1139,10 @@ class CapturedStream { } FILE* const file = posix::FOpen(filename_.c_str(), "r"); + if (file == nullptr) { + GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_ + << " for capturing stream."; + } const std::string content = ReadEntireFile(file); posix::FClose(file); return content; @@ -1169,13 +1256,6 @@ void SetInjectableArgvs(const std::vector<std::string>& new_argvs) { new std::vector<std::string>(new_argvs.begin(), new_argvs.end())); } -#if GTEST_HAS_GLOBAL_STRING -void SetInjectableArgvs(const std::vector< ::string>& new_argvs) { - SetInjectableArgvs( - new std::vector<std::string>(new_argvs.begin(), new_argvs.end())); -} -#endif // GTEST_HAS_GLOBAL_STRING - void ClearInjectableArgvs() { delete g_injected_test_argvs; g_injected_test_argvs = nullptr; @@ -1250,7 +1330,7 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) { // Reads and returns the Boolean environment variable corresponding to // the given flag; if it's not set, returns default_value. // -// The value is considered true iff it's not "0". +// The value is considered true if it's not "0". bool BoolFromGTestEnv(const char* flag, bool default_value) { #if defined(GTEST_GET_BOOL_FROM_ENV_) return GTEST_GET_BOOL_FROM_ENV_(flag, default_value); |