30#include "gtest/internal/gtest-port.h"
55#include <mach/mach_init.h>
57#include <mach/vm_map.h>
60#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
61 GTEST_OS_NETBSD || GTEST_OS_OPENBSD
62#include <sys/sysctl.h>
63#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
71#include <sys/procfs.h>
80#include <zircon/process.h>
81#include <zircon/syscalls.h>
84#include "gtest/gtest-message.h"
85#include "gtest/gtest-spi.h"
86#include "gtest/internal/gtest-internal.h"
87#include "gtest/internal/gtest-string.h"
93#if GTEST_OS_LINUX || GTEST_OS_GNU_HURD
97T ReadProcFileField(
const std::string& filename,
int field) {
99 std::ifstream file(filename.c_str());
100 while (field-- > 0) {
111 const std::string filename =
112 (Message() <<
"/proc/" << getpid() <<
"/stat").GetString();
113 return ReadProcFileField<size_t>(filename, 19);
119 const task_t task = mach_task_self();
120 mach_msg_type_number_t thread_count;
121 thread_act_array_t thread_list;
122 const kern_return_t status = task_threads(task, &thread_list, &thread_count);
123 if (status == KERN_SUCCESS) {
126 vm_deallocate(task,
reinterpret_cast<vm_address_t
>(thread_list),
127 sizeof(thread_t) * thread_count);
128 return static_cast<size_t>(thread_count);
134#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
139#define KERN_PROC KERN_PROC2
140#define kinfo_proc kinfo_proc2
143#if GTEST_OS_DRAGONFLY
144#define KP_NLWP(kp) (kp.kp_nthreads)
145#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
146#define KP_NLWP(kp) (kp.ki_numthreads)
148#define KP_NLWP(kp) (kp.p_nlwps)
160 sizeof(
struct kinfo_proc),
164 u_int miblen =
sizeof(mib) /
sizeof(mib[0]);
165 struct kinfo_proc info;
166 size_t size =
sizeof(info);
167 if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
170 return static_cast<size_t>(KP_NLWP(info));
172#elif GTEST_OS_OPENBSD
180 KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
182 sizeof(
struct kinfo_proc),
185 u_int miblen =
sizeof(mib) /
sizeof(mib[0]);
189 if (sysctl(mib, miblen, NULL, &size, NULL, 0)) {
193 mib[5] =
static_cast<int>(size /
static_cast<size_t>(mib[4]));
196 struct kinfo_proc info[mib[5]];
197 if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
203 for (
size_t i = 0; i < size /
static_cast<size_t>(mib[4]); i++) {
204 if (info[i].p_tid != -1) nthreads++;
214 const int fd = open(
"/proc/self/as", O_RDONLY);
218 procfs_info process_info;
220 devctl(fd, DCMD_PROC_INFO, &process_info,
sizeof(process_info),
nullptr);
223 return static_cast<size_t>(process_info.num_threads);
232 struct procentry64 entry;
233 pid_t pid = getpid();
234 int status = getprocs64(&entry,
sizeof(entry),
nullptr, 0, &pid, 1);
236 return entry.pi_thcount;
242#elif GTEST_OS_FUCHSIA
248 zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS_THREADS,
249 &dummy_buffer, 0,
nullptr, &avail);
250 if (status == ZX_OK) {
267#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
269AutoHandle::AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
271AutoHandle::AutoHandle(Handle handle) : handle_(handle) {}
273AutoHandle::~AutoHandle() { Reset(); }
275AutoHandle::Handle AutoHandle::Get()
const {
return handle_; }
277void AutoHandle::Reset() { Reset(INVALID_HANDLE_VALUE); }
279void AutoHandle::Reset(HANDLE handle) {
281 if (handle_ != handle) {
283 ::CloseHandle(handle_);
287 GTEST_CHECK_(!IsCloseable())
288 <<
"Resetting a valid handle to itself is likely a programmer error "
289 "and thus not allowed.";
293bool AutoHandle::IsCloseable()
const {
296 return handle_ !=
nullptr && handle_ != INVALID_HANDLE_VALUE;
300 : owner_thread_id_(0),
302 critical_section_init_phase_(0),
303 critical_section_(new CRITICAL_SECTION) {
304 ::InitializeCriticalSection(critical_section_);
310 if (type_ == kDynamic) {
311 ::DeleteCriticalSection(critical_section_);
312 delete critical_section_;
313 critical_section_ =
nullptr;
318 ThreadSafeLazyInit();
319 ::EnterCriticalSection(critical_section_);
320 owner_thread_id_ = ::GetCurrentThreadId();
323void Mutex::Unlock() {
324 ThreadSafeLazyInit();
328 owner_thread_id_ = 0;
329 ::LeaveCriticalSection(critical_section_);
334void Mutex::AssertHeld() {
335 ThreadSafeLazyInit();
336 GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
337 <<
"The current thread is not holding the mutex @" <<
this;
351class MemoryIsNotDeallocated {
353 MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
354 old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
357 (void)_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
360 ~MemoryIsNotDeallocated() {
362 (void)_CrtSetDbgFlag(old_crtdbg_flag_);
366 int old_crtdbg_flag_;
368 MemoryIsNotDeallocated(
const MemoryIsNotDeallocated&) =
delete;
369 MemoryIsNotDeallocated& operator=(
const MemoryIsNotDeallocated&) =
delete;
376void Mutex::ThreadSafeLazyInit() {
378 if (type_ == kStatic) {
380 ::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
384 owner_thread_id_ = 0;
388 MemoryIsNotDeallocated memory_is_not_deallocated;
390 critical_section_ =
new CRITICAL_SECTION;
392 ::InitializeCriticalSection(critical_section_);
395 GTEST_CHECK_(::InterlockedCompareExchange(&critical_section_init_phase_,
401 while (::InterlockedCompareExchange(&critical_section_init_phase_, 2L,
414 <<
"Unexpected value of critical_section_init_phase_ "
415 <<
"while initializing a static mutex.";
422class ThreadWithParamSupport :
public ThreadWithParamBase {
424 static HANDLE CreateThread(Runnable* runnable,
425 Notification* thread_can_start) {
426 ThreadMainParam* param =
new ThreadMainParam(runnable, thread_can_start);
428 HANDLE thread_handle = ::CreateThread(
431 &ThreadWithParamSupport::ThreadMain,
435 GTEST_CHECK_(thread_handle !=
nullptr)
436 <<
"CreateThread failed with error " << ::GetLastError() <<
".";
437 if (thread_handle ==
nullptr) {
440 return thread_handle;
444 struct ThreadMainParam {
445 ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
446 : runnable_(runnable), thread_can_start_(thread_can_start) {}
447 std::unique_ptr<Runnable> runnable_;
449 Notification* thread_can_start_;
452 static DWORD WINAPI ThreadMain(
void* ptr) {
454 std::unique_ptr<ThreadMainParam> param(
static_cast<ThreadMainParam*
>(ptr));
455 if (param->thread_can_start_ !=
nullptr)
456 param->thread_can_start_->WaitForNotification();
457 param->runnable_->Run();
462 ThreadWithParamSupport();
464 ThreadWithParamSupport(
const ThreadWithParamSupport&) =
delete;
465 ThreadWithParamSupport& operator=(
const ThreadWithParamSupport&) =
delete;
470ThreadWithParamBase::ThreadWithParamBase(Runnable* runnable,
471 Notification* thread_can_start)
473 ThreadWithParamSupport::CreateThread(runnable, thread_can_start)) {}
475ThreadWithParamBase::~ThreadWithParamBase() { Join(); }
477void ThreadWithParamBase::Join() {
478 GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
479 <<
"Failed to join the thread with error " << ::GetLastError() <<
".";
486class ThreadLocalRegistryImpl {
490 static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
491 const ThreadLocalBase* thread_local_instance) {
493 MemoryIsNotDeallocated memory_is_not_deallocated;
495 DWORD current_thread = ::GetCurrentThreadId();
496 MutexLock lock(&mutex_);
497 ThreadIdToThreadLocals*
const thread_to_thread_locals =
498 GetThreadLocalsMapLocked();
499 ThreadIdToThreadLocals::iterator thread_local_pos =
500 thread_to_thread_locals->find(current_thread);
501 if (thread_local_pos == thread_to_thread_locals->end()) {
503 thread_to_thread_locals
504 ->insert(std::make_pair(current_thread, ThreadLocalValues()))
506 StartWatcherThreadFor(current_thread);
508 ThreadLocalValues& thread_local_values = thread_local_pos->second;
509 ThreadLocalValues::iterator value_pos =
510 thread_local_values.find(thread_local_instance);
511 if (value_pos == thread_local_values.end()) {
514 .insert(std::make_pair(
515 thread_local_instance,
516 std::shared_ptr<ThreadLocalValueHolderBase>(
517 thread_local_instance->NewValueForCurrentThread())))
520 return value_pos->second.get();
523 static void OnThreadLocalDestroyed(
524 const ThreadLocalBase* thread_local_instance) {
525 std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
529 MutexLock lock(&mutex_);
530 ThreadIdToThreadLocals*
const thread_to_thread_locals =
531 GetThreadLocalsMapLocked();
532 for (ThreadIdToThreadLocals::iterator it =
533 thread_to_thread_locals->begin();
534 it != thread_to_thread_locals->end(); ++it) {
535 ThreadLocalValues& thread_local_values = it->second;
536 ThreadLocalValues::iterator value_pos =
537 thread_local_values.find(thread_local_instance);
538 if (value_pos != thread_local_values.end()) {
539 value_holders.push_back(value_pos->second);
540 thread_local_values.erase(value_pos);
550 static void OnThreadExit(DWORD thread_id) {
551 GTEST_CHECK_(thread_id != 0) << ::GetLastError();
552 std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
556 MutexLock lock(&mutex_);
557 ThreadIdToThreadLocals*
const thread_to_thread_locals =
558 GetThreadLocalsMapLocked();
559 ThreadIdToThreadLocals::iterator thread_local_pos =
560 thread_to_thread_locals->find(thread_id);
561 if (thread_local_pos != thread_to_thread_locals->end()) {
562 ThreadLocalValues& thread_local_values = thread_local_pos->second;
563 for (ThreadLocalValues::iterator value_pos =
564 thread_local_values.begin();
565 value_pos != thread_local_values.end(); ++value_pos) {
566 value_holders.push_back(value_pos->second);
568 thread_to_thread_locals->erase(thread_local_pos);
577 typedef std::map<
const ThreadLocalBase*,
578 std::shared_ptr<ThreadLocalValueHolderBase> >
582 typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
586 typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
588 static void StartWatcherThreadFor(DWORD thread_id) {
592 ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id);
593 GTEST_CHECK_(thread !=
nullptr);
596 DWORD watcher_thread_id;
597 HANDLE watcher_thread = ::CreateThread(
600 &ThreadLocalRegistryImpl::WatcherThreadFunc,
601 reinterpret_cast<LPVOID
>(
new ThreadIdAndHandle(thread_id, thread)),
602 CREATE_SUSPENDED, &watcher_thread_id);
603 GTEST_CHECK_(watcher_thread !=
nullptr)
604 <<
"CreateThread failed with error " << ::GetLastError() <<
".";
607 ::SetThreadPriority(watcher_thread,
608 ::GetThreadPriority(::GetCurrentThread()));
609 ::ResumeThread(watcher_thread);
610 ::CloseHandle(watcher_thread);
615 static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
616 const ThreadIdAndHandle* tah =
617 reinterpret_cast<const ThreadIdAndHandle*
>(param);
618 GTEST_CHECK_(::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
619 OnThreadExit(tah->first);
620 ::CloseHandle(tah->second);
626 static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
629 MemoryIsNotDeallocated memory_is_not_deallocated;
631 static ThreadIdToThreadLocals* map =
new ThreadIdToThreadLocals();
638 static Mutex thread_map_mutex_;
641Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
642Mutex ThreadLocalRegistryImpl::thread_map_mutex_(
643 Mutex::kStaticMutex);
645ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
646 const ThreadLocalBase* thread_local_instance) {
647 return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
648 thread_local_instance);
651void ThreadLocalRegistry::OnThreadLocalDestroyed(
652 const ThreadLocalBase* thread_local_instance) {
653 ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
658#if GTEST_USES_POSIX_RE
668 regfree(&partial_regex_);
669 regfree(&full_regex_);
671 free(
const_cast<char*
>(pattern_));
675bool RE::FullMatch(
const char* str,
const RE& re) {
676 if (!re.is_valid_)
return false;
679 return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
684bool RE::PartialMatch(
const char* str,
const RE& re) {
685 if (!re.is_valid_)
return false;
688 return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
692void RE::Init(
const char* regex) {
693 pattern_ = posix::StrDup(regex);
697 const size_t full_regex_len = strlen(regex) + 10;
698 char*
const full_pattern =
new char[full_regex_len];
700 snprintf(full_pattern, full_regex_len,
"^(%s)$", regex);
701 is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
711 const char*
const partial_regex = (*regex ==
'\0') ?
"()" : regex;
712 is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
714 EXPECT_TRUE(is_valid_)
715 <<
"Regular expression \"" << regex
716 <<
"\" is not a valid POSIX Extended regular expression.";
718 delete[] full_pattern;
721#elif GTEST_USES_SIMPLE_RE
725bool IsInSet(
char ch,
const char* str) {
726 return ch !=
'\0' && strchr(str, ch) !=
nullptr;
732bool IsAsciiDigit(
char ch) {
return '0' <= ch && ch <=
'9'; }
733bool IsAsciiPunct(
char ch) {
734 return IsInSet(ch,
"^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
736bool IsRepeat(
char ch) {
return IsInSet(ch,
"?*+"); }
737bool IsAsciiWhiteSpace(
char ch) {
return IsInSet(ch,
" \f\n\r\t\v"); }
738bool IsAsciiWordChar(
char ch) {
739 return (
'a' <= ch && ch <=
'z') || (
'A' <= ch && ch <=
'Z') ||
740 (
'0' <= ch && ch <=
'9') || ch ==
'_';
744bool IsValidEscape(
char c) {
745 return (IsAsciiPunct(c) || IsInSet(c,
"dDfnrsStvwW"));
750bool AtomMatchesChar(
bool escaped,
char pattern_char,
char ch) {
752 switch (pattern_char) {
754 return IsAsciiDigit(ch);
756 return !IsAsciiDigit(ch);
764 return IsAsciiWhiteSpace(ch);
766 return !IsAsciiWhiteSpace(ch);
772 return IsAsciiWordChar(ch);
774 return !IsAsciiWordChar(ch);
776 return IsAsciiPunct(pattern_char) && pattern_char == ch;
779 return (pattern_char ==
'.' && ch !=
'\n') || pattern_char == ch;
783static std::string FormatRegexSyntaxError(
const char* regex,
int index) {
784 return (Message() <<
"Syntax error at index " << index
785 <<
" in simple regular expression \"" << regex <<
"\": ")
791bool ValidateRegex(
const char* regex) {
792 if (regex ==
nullptr) {
793 ADD_FAILURE() <<
"NULL is not a valid simple regular expression.";
797 bool is_valid =
true;
800 bool prev_repeatable =
false;
801 for (
int i = 0; regex[i]; i++) {
802 if (regex[i] ==
'\\') {
804 if (regex[i] ==
'\0') {
805 ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
806 <<
"'\\' cannot appear at the end.";
810 if (!IsValidEscape(regex[i])) {
811 ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
812 <<
"invalid escape sequence \"\\" << regex[i] <<
"\".";
815 prev_repeatable =
true;
817 const char ch = regex[i];
819 if (ch ==
'^' && i > 0) {
820 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
821 <<
"'^' can only appear at the beginning.";
823 }
else if (ch ==
'$' && regex[i + 1] !=
'\0') {
824 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
825 <<
"'$' can only appear at the end.";
827 }
else if (IsInSet(ch,
"()[]{}|")) {
828 ADD_FAILURE() << FormatRegexSyntaxError(regex, i) <<
"'" << ch
829 <<
"' is unsupported.";
831 }
else if (IsRepeat(ch) && !prev_repeatable) {
832 ADD_FAILURE() << FormatRegexSyntaxError(regex, i) <<
"'" << ch
833 <<
"' can only follow a repeatable token.";
837 prev_repeatable = !IsInSet(ch,
"^$?*+");
851bool MatchRepetitionAndRegexAtHead(
bool escaped,
char c,
char repeat,
852 const char* regex,
const char* str) {
853 const size_t min_count = (repeat ==
'+') ? 1 : 0;
854 const size_t max_count = (repeat ==
'?') ? 1 : static_cast<size_t>(-1) - 1;
858 for (
size_t i = 0; i <= max_count; ++i) {
860 if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
867 if (str[i] ==
'\0' || !AtomMatchesChar(escaped, c, str[i]))
return false;
875bool MatchRegexAtHead(
const char* regex,
const char* str) {
881 if (*regex ==
'$')
return *str ==
'\0';
884 const bool escaped = *regex ==
'\\';
885 if (escaped) ++regex;
886 if (IsRepeat(regex[1])) {
890 return MatchRepetitionAndRegexAtHead(escaped, regex[0], regex[1], regex + 2,
896 return (*str !=
'\0') && AtomMatchesChar(escaped, *regex, *str) &&
897 MatchRegexAtHead(regex + 1, str + 1);
909bool MatchRegexAnywhere(
const char* regex,
const char* str) {
910 if (regex ==
nullptr || str ==
nullptr)
return false;
912 if (*regex ==
'^')
return MatchRegexAtHead(regex + 1, str);
916 if (MatchRegexAtHead(regex, str))
return true;
917 }
while (*str++ !=
'\0');
924 free(
const_cast<char*
>(pattern_));
925 free(
const_cast<char*
>(full_pattern_));
929bool RE::FullMatch(
const char* str,
const RE& re) {
930 return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
935bool RE::PartialMatch(
const char* str,
const RE& re) {
936 return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
940void RE::Init(
const char* regex) {
941 pattern_ = full_pattern_ =
nullptr;
942 if (regex !=
nullptr) {
943 pattern_ = posix::StrDup(regex);
946 is_valid_ = ValidateRegex(regex);
952 const size_t len = strlen(regex);
956 char* buffer =
static_cast<char*
>(malloc(len + 3));
957 full_pattern_ = buffer;
964 memcpy(buffer, regex, len);
967 if (len == 0 || regex[len - 1] !=
'$')
980 const std::string file_name(file ==
nullptr ?
kUnknownFile : file);
983 return file_name +
":";
986 return file_name +
"(" + StreamableToString(line) +
"):";
988 return file_name +
":" + StreamableToString(line) +
":";
999 const std::string file_name(file ==
nullptr ?
kUnknownFile : file);
1004 return file_name +
":" + StreamableToString(line);
1007GTestLog::GTestLog(GTestLogSeverity severity,
const char* file,
int line)
1008 : severity_(severity) {
1009 const char*
const marker = severity == GTEST_INFO ?
"[ INFO ]"
1010 : severity == GTEST_WARNING ?
"[WARNING]"
1011 : severity == GTEST_ERROR ?
"[ ERROR ]"
1013 GetStream() << ::std::endl
1019GTestLog::~GTestLog() {
1020 GetStream() << ::std::endl;
1021 if (severity_ == GTEST_FATAL) {
1029GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
1031#if GTEST_HAS_STREAM_REDIRECTION
1034class CapturedStream {
1037 explicit CapturedStream(
int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
1039 char temp_dir_path[MAX_PATH + 1] = {
'\0'};
1040 char temp_file_path[MAX_PATH + 1] = {
'\0'};
1042 ::GetTempPathA(
sizeof(temp_dir_path), temp_dir_path);
1043 const UINT success = ::GetTempFileNameA(temp_dir_path,
"gtest_redir",
1046 GTEST_CHECK_(success != 0)
1047 <<
"Unable to create a temporary file in " << temp_dir_path;
1048 const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
1049 GTEST_CHECK_(captured_fd != -1)
1050 <<
"Unable to open temporary file " << temp_file_path;
1051 filename_ = temp_file_path;
1055 std::string name_template;
1057#if GTEST_OS_LINUX_ANDROID
1069 name_template =
"/data/local/tmp/";
1071 char user_temp_dir[PATH_MAX + 1];
1086 ::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir,
sizeof(user_temp_dir));
1088 name_template = user_temp_dir;
1089 if (name_template.back() != GTEST_PATH_SEP_[0])
1090 name_template.push_back(GTEST_PATH_SEP_[0]);
1092 name_template =
"/tmp/";
1094 name_template.append(
"gtest_captured_stream.XXXXXX");
1102 const int captured_fd = ::mkstemp(
const_cast<char*
>(name_template.data()));
1103 if (captured_fd == -1) {
1105 <<
"Failed to create tmp file " << name_template
1106 <<
" for test; does the test have access to the /tmp directory?";
1108 filename_ = std::move(name_template);
1111 dup2(captured_fd, fd_);
1115 ~CapturedStream() { remove(filename_.c_str()); }
1117 std::string GetCapturedString() {
1118 if (uncaptured_fd_ != -1) {
1121 dup2(uncaptured_fd_, fd_);
1122 close(uncaptured_fd_);
1123 uncaptured_fd_ = -1;
1126 FILE*
const file = posix::FOpen(filename_.c_str(),
"r");
1127 if (file ==
nullptr) {
1128 GTEST_LOG_(FATAL) <<
"Failed to open tmp file " << filename_
1129 <<
" for capturing stream.";
1132 posix::FClose(file);
1140 ::std::string filename_;
1142 CapturedStream(
const CapturedStream&) =
delete;
1143 CapturedStream& operator=(
const CapturedStream&) =
delete;
1146GTEST_DISABLE_MSC_DEPRECATED_POP_()
1148static CapturedStream* g_captured_stderr =
nullptr;
1149static CapturedStream* g_captured_stdout =
nullptr;
1152static
void CaptureStream(
int fd, const
char* stream_name,
1153 CapturedStream** stream) {
1154 if (*stream !=
nullptr) {
1155 GTEST_LOG_(FATAL) <<
"Only one " << stream_name
1156 <<
" capturer can exist at a time.";
1158 *stream =
new CapturedStream(fd);
1162static std::string GetCapturedStream(CapturedStream** captured_stream) {
1163 const std::string content = (*captured_stream)->GetCapturedString();
1165 delete *captured_stream;
1166 *captured_stream =
nullptr;
1171#if defined(_MSC_VER) || defined(__BORLANDC__)
1173const int kStdOutFileno = 1;
1174const int kStdErrFileno = 2;
1176const int kStdOutFileno = STDOUT_FILENO;
1177const int kStdErrFileno = STDERR_FILENO;
1181void CaptureStdout() {
1182 CaptureStream(kStdOutFileno,
"stdout", &g_captured_stdout);
1186void CaptureStderr() {
1187 CaptureStream(kStdErrFileno,
"stderr", &g_captured_stderr);
1191std::string GetCapturedStdout() {
1192 return GetCapturedStream(&g_captured_stdout);
1196std::string GetCapturedStderr() {
1197 return GetCapturedStream(&g_captured_stderr);
1203 fseek(file, 0, SEEK_END);
1204 return static_cast<size_t>(ftell(file));
1209 char*
const buffer =
new char[file_size];
1211 size_t bytes_last_read = 0;
1212 size_t bytes_read = 0;
1214 fseek(file, 0, SEEK_SET);
1220 fread(buffer + bytes_read, 1, file_size - bytes_read, file);
1221 bytes_read += bytes_last_read;
1222 }
while (bytes_last_read > 0 && bytes_read < file_size);
1224 const std::string content(buffer, bytes_read);
1230#if GTEST_HAS_DEATH_TEST
1231static const std::vector<std::string>* g_injected_test_argvs =
1234std::vector<std::string> GetInjectableArgvs() {
1235 if (g_injected_test_argvs !=
nullptr) {
1236 return *g_injected_test_argvs;
1241void SetInjectableArgvs(
const std::vector<std::string>* new_argvs) {
1242 if (g_injected_test_argvs != new_argvs)
delete g_injected_test_argvs;
1243 g_injected_test_argvs = new_argvs;
1246void SetInjectableArgvs(
const std::vector<std::string>& new_argvs) {
1248 new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
1251void ClearInjectableArgvs() {
1252 delete g_injected_test_argvs;
1253 g_injected_test_argvs =
nullptr;
1257#if GTEST_OS_WINDOWS_MOBILE
1261 TerminateProcess(GetCurrentProcess(), 1);
1270 const std::string full_flag =
1271 (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
1274 for (
size_t i = 0; i != full_flag.length(); i++) {
1275 env_var << ToUpper(full_flag.c_str()[i]);
1278 return env_var.GetString();
1284bool ParseInt32(
const Message& src_text,
const char* str, int32_t* value) {
1286 char* end =
nullptr;
1287 const long long_value = strtol(str, &end, 10);
1293 msg <<
"WARNING: " << src_text
1294 <<
" is expected to be a 32-bit integer, but actually"
1295 <<
" has value \"" << str <<
"\".\n";
1296 printf(
"%s", msg.GetString().c_str());
1302 const auto result =
static_cast<int32_t
>(long_value);
1303 if (long_value == LONG_MAX || long_value == LONG_MIN ||
1306 result != long_value
1310 msg <<
"WARNING: " << src_text
1311 <<
" is expected to be a 32-bit integer, but actually"
1312 <<
" has value " << str <<
", which overflows.\n";
1313 printf(
"%s", msg.GetString().c_str());
1284bool ParseInt32(
const Message& src_text,
const char* str, int32_t* value) {
…}
1327#if defined(GTEST_GET_BOOL_FROM_ENV_)
1328 return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
1331 const char*
const string_value = posix::GetEnv(env_var.c_str());
1332 return string_value ==
nullptr ? default_value
1333 : strcmp(string_value,
"0") != 0;
1341#if defined(GTEST_GET_INT32_FROM_ENV_)
1342 return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
1345 const char*
const string_value = posix::GetEnv(env_var.c_str());
1346 if (string_value ==
nullptr) {
1348 return default_value;
1351 int32_t result = default_value;
1352 if (!
ParseInt32(Message() <<
"Environment variable " << env_var, string_value,
1354 printf(
"The default value %s is used.\n",
1355 (Message() << default_value).GetString().c_str());
1357 return default_value;
1373 std::string default_value_for_output_flag =
"";
1374 const char* xml_output_file_env = posix::GetEnv(
"XML_OUTPUT_FILE");
1375 if (
nullptr != xml_output_file_env) {
1376 default_value_for_output_flag = std::string(
"xml:") + xml_output_file_env;
1378 return default_value_for_output_flag;
1384#if defined(GTEST_GET_STRING_FROM_ENV_)
1385 return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
1388 const char*
const value = posix::GetEnv(env_var.c_str());
1389 return value ==
nullptr ? default_value : value;
size_t GetFileSize(FILE *file)
const char * StringFromGTestEnv(const char *flag, const char *default_value)
std::string OutputFlagAlsoCheckEnvVar()
bool BoolFromGTestEnv(const char *flag, bool default_value)
GTEST_API_::std::string FormatCompilerIndependentFileLocation(const char *file, int line)
std::string ReadEntireFile(FILE *file)
GTEST_API_::std::string FormatFileLocation(const char *file, int line)
bool ParseInt32(const Message &src_text, const char *str, int32_t *value)
static std::string FlagToEnvVar(const char *flag)
int32_t Int32FromGTestEnv(const char *flag, int32_t default_value)
const char kUnknownFile[]