1 // Copyright 2008, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "gtest/internal/gtest-port.h"
45 #ifdef GTEST_OS_WINDOWS
50 #include <map> // Used in ThreadLocal.
56 #endif // GTEST_OS_WINDOWS
59 #include <mach/mach_init.h>
60 #include <mach/task.h>
61 #include <mach/vm_map.h>
62 #endif // GTEST_OS_MAC
64 #if defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) || \
65 defined(GTEST_OS_GNU_KFREEBSD) || defined(GTEST_OS_NETBSD) || \
66 defined(GTEST_OS_OPENBSD)
67 #include <sys/sysctl.h>
68 #if defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) || \
69 defined(GTEST_OS_GNU_KFREEBSD)
77 #include <sys/procfs.h>
78 #endif // GTEST_OS_QNX
82 #include <sys/types.h>
83 #endif // GTEST_OS_AIX
85 #ifdef GTEST_OS_FUCHSIA
86 #include <zircon/process.h>
87 #include <zircon/syscalls.h>
88 #endif // GTEST_OS_FUCHSIA
90 #include "gtest/gtest-message.h"
91 #include "gtest/gtest-spi.h"
92 #include "gtest/internal/gtest-internal.h"
93 #include "gtest/internal/gtest-string.h"
94 #include "src/gtest-internal-inl.h"
99 #if defined(GTEST_OS_LINUX) || defined(GTEST_OS_GNU_HURD)
102 template <typename T
>
103 T
ReadProcFileField(const std::string
& filename
, int field
) {
105 std::ifstream
file(filename
.c_str());
106 while (field
-- > 0) {
115 // Returns the number of active threads, or 0 when there is an error.
116 size_t GetThreadCount() {
117 const std::string filename
=
118 (Message() << "/proc/" << getpid() << "/stat").GetString();
119 return ReadProcFileField
<size_t>(filename
, 19);
122 #elif defined(GTEST_OS_MAC)
124 size_t GetThreadCount() {
125 const task_t task
= mach_task_self();
126 mach_msg_type_number_t thread_count
;
127 thread_act_array_t thread_list
;
128 const kern_return_t status
= task_threads(task
, &thread_list
, &thread_count
);
129 if (status
== KERN_SUCCESS
) {
130 // task_threads allocates resources in thread_list and we need to free them
132 vm_deallocate(task
, reinterpret_cast<vm_address_t
>(thread_list
),
133 sizeof(thread_t
) * thread_count
);
134 return static_cast<size_t>(thread_count
);
140 #elif defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_FREEBSD) || \
141 defined(GTEST_OS_GNU_KFREEBSD) || defined(GTEST_OS_NETBSD)
143 #ifdef GTEST_OS_NETBSD
145 #define KERN_PROC KERN_PROC2
146 #define kinfo_proc kinfo_proc2
149 #ifdef GTEST_OS_DRAGONFLY
150 #define KP_NLWP(kp) (kp.kp_nthreads)
151 #elif defined(GTEST_OS_FREEBSD) || defined(GTEST_OS_GNU_KFREEBSD)
152 #define KP_NLWP(kp) (kp.ki_numthreads)
153 #elif defined(GTEST_OS_NETBSD)
154 #define KP_NLWP(kp) (kp.p_nlwps)
157 // Returns the number of threads running in the process, or 0 to indicate that
158 // we cannot detect it.
159 size_t GetThreadCount() {
165 #ifdef GTEST_OS_NETBSD
166 sizeof(struct kinfo_proc
),
170 u_int miblen
= sizeof(mib
) / sizeof(mib
[0]);
171 struct kinfo_proc info
;
172 size_t size
= sizeof(info
);
173 if (sysctl(mib
, miblen
, &info
, &size
, NULL
, 0)) {
176 return static_cast<size_t>(KP_NLWP(info
));
178 #elif defined(GTEST_OS_OPENBSD)
180 // Returns the number of threads running in the process, or 0 to indicate that
181 // we cannot detect it.
182 size_t GetThreadCount() {
186 KERN_PROC_PID
| KERN_PROC_SHOW_THREADS
,
188 sizeof(struct kinfo_proc
),
191 u_int miblen
= sizeof(mib
) / sizeof(mib
[0]);
193 // get number of structs
195 if (sysctl(mib
, miblen
, NULL
, &size
, NULL
, 0)) {
199 mib
[5] = static_cast<int>(size
/ static_cast<size_t>(mib
[4]));
201 // populate array of structs
202 std::vector
<struct kinfo_proc
> info(mib
[5]);
203 if (sysctl(mib
, miblen
, info
.data(), &size
, NULL
, 0)) {
207 // exclude empty members
209 for (size_t i
= 0; i
< size
/ static_cast<size_t>(mib
[4]); i
++) {
210 if (info
[i
].p_tid
!= -1) nthreads
++;
215 #elif defined(GTEST_OS_QNX)
217 // Returns the number of threads running in the process, or 0 to indicate that
218 // we cannot detect it.
219 size_t GetThreadCount() {
220 const int fd
= open("/proc/self/as", O_RDONLY
);
224 procfs_info process_info
;
226 devctl(fd
, DCMD_PROC_INFO
, &process_info
, sizeof(process_info
), nullptr);
229 return static_cast<size_t>(process_info
.num_threads
);
235 #elif defined(GTEST_OS_AIX)
237 size_t GetThreadCount() {
238 struct procentry64 entry
;
239 pid_t pid
= getpid();
240 int status
= getprocs64(&entry
, sizeof(entry
), nullptr, 0, &pid
, 1);
242 return entry
.pi_thcount
;
248 #elif defined(GTEST_OS_FUCHSIA)
250 size_t GetThreadCount() {
254 zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS_THREADS
,
255 &dummy_buffer
, 0, nullptr, &avail
);
256 if (status
== ZX_OK
) {
265 size_t GetThreadCount() {
266 // There's no portable way to detect the number of threads, so we just
267 // return 0 to indicate that we cannot detect it.
271 #endif // GTEST_OS_LINUX
273 #if defined(GTEST_IS_THREADSAFE) && defined(GTEST_OS_WINDOWS)
275 AutoHandle::AutoHandle() : handle_(INVALID_HANDLE_VALUE
) {}
277 AutoHandle::AutoHandle(Handle handle
) : handle_(handle
) {}
279 AutoHandle::~AutoHandle() { Reset(); }
281 AutoHandle::Handle
AutoHandle::Get() const { return handle_
; }
283 void AutoHandle::Reset() { Reset(INVALID_HANDLE_VALUE
); }
285 void AutoHandle::Reset(HANDLE handle
) {
286 // Resetting with the same handle we already own is invalid.
287 if (handle_
!= handle
) {
289 ::CloseHandle(handle_
);
293 GTEST_CHECK_(!IsCloseable())
294 << "Resetting a valid handle to itself is likely a programmer error "
295 "and thus not allowed.";
299 bool AutoHandle::IsCloseable() const {
300 // Different Windows APIs may use either of these values to represent an
302 return handle_
!= nullptr && handle_
!= INVALID_HANDLE_VALUE
;
306 : owner_thread_id_(0),
308 critical_section_init_phase_(0),
309 critical_section_(new CRITICAL_SECTION
) {
310 ::InitializeCriticalSection(critical_section_
);
314 // Static mutexes are leaked intentionally. It is not thread-safe to try
316 if (type_
== kDynamic
) {
317 ::DeleteCriticalSection(critical_section_
);
318 delete critical_section_
;
319 critical_section_
= nullptr;
324 ThreadSafeLazyInit();
325 ::EnterCriticalSection(critical_section_
);
326 owner_thread_id_
= ::GetCurrentThreadId();
329 void Mutex::Unlock() {
330 ThreadSafeLazyInit();
331 // We don't protect writing to owner_thread_id_ here, as it's the
332 // caller's responsibility to ensure that the current thread holds the
333 // mutex when this is called.
334 owner_thread_id_
= 0;
335 ::LeaveCriticalSection(critical_section_
);
338 // Does nothing if the current thread holds the mutex. Otherwise, crashes
339 // with high probability.
340 void Mutex::AssertHeld() {
341 ThreadSafeLazyInit();
342 GTEST_CHECK_(owner_thread_id_
== ::GetCurrentThreadId())
343 << "The current thread is not holding the mutex @" << this;
349 // Use the RAII idiom to flag mem allocs that are intentionally never
350 // deallocated. The motivation is to silence the false positive mem leaks
351 // that are reported by the debug version of MS's CRT which can only detect
352 // if an alloc is missing a matching deallocation.
354 // MemoryIsNotDeallocated memory_is_not_deallocated;
355 // critical_section_ = new CRITICAL_SECTION;
357 class MemoryIsNotDeallocated
{
359 MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
360 old_crtdbg_flag_
= _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG
);
361 // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
362 // doesn't report mem leak if there's no matching deallocation.
363 (void)_CrtSetDbgFlag(old_crtdbg_flag_
& ~_CRTDBG_ALLOC_MEM_DF
);
366 ~MemoryIsNotDeallocated() {
367 // Restore the original _CRTDBG_ALLOC_MEM_DF flag
368 (void)_CrtSetDbgFlag(old_crtdbg_flag_
);
372 int old_crtdbg_flag_
;
374 MemoryIsNotDeallocated(const MemoryIsNotDeallocated
&) = delete;
375 MemoryIsNotDeallocated
& operator=(const MemoryIsNotDeallocated
&) = delete;
381 // Initializes owner_thread_id_ and critical_section_ in static mutexes.
382 void Mutex::ThreadSafeLazyInit() {
383 // Dynamic mutexes are initialized in the constructor.
384 if (type_
== kStatic
) {
386 ::InterlockedCompareExchange(&critical_section_init_phase_
, 1L, 0L)) {
388 // If critical_section_init_phase_ was 0 before the exchange, we
389 // are the first to test it and need to perform the initialization.
390 owner_thread_id_
= 0;
392 // Use RAII to flag that following mem alloc is never deallocated.
394 MemoryIsNotDeallocated memory_is_not_deallocated
;
396 critical_section_
= new CRITICAL_SECTION
;
398 ::InitializeCriticalSection(critical_section_
);
399 // Updates the critical_section_init_phase_ to 2 to signal
400 // initialization complete.
401 GTEST_CHECK_(::InterlockedCompareExchange(&critical_section_init_phase_
,
405 // Somebody else is already initializing the mutex; spin until they
407 while (::InterlockedCompareExchange(&critical_section_init_phase_
, 2L,
409 // Possibly yields the rest of the thread's time slice to other
416 break; // The mutex is already initialized and ready for use.
420 << "Unexpected value of critical_section_init_phase_ "
421 << "while initializing a static mutex.";
428 class ThreadWithParamSupport
: public ThreadWithParamBase
{
430 static HANDLE
CreateThread(Runnable
* runnable
,
431 Notification
* thread_can_start
) {
432 ThreadMainParam
* param
= new ThreadMainParam(runnable
, thread_can_start
);
434 HANDLE thread_handle
= ::CreateThread(
435 nullptr, // Default security.
436 0, // Default stack size.
437 &ThreadWithParamSupport::ThreadMain
,
438 param
, // Parameter to ThreadMainStatic
439 0x0, // Default creation flags.
440 &thread_id
); // Need a valid pointer for the call to work under Win98.
441 GTEST_CHECK_(thread_handle
!= nullptr)
442 << "CreateThread failed with error " << ::GetLastError() << ".";
443 if (thread_handle
== nullptr) {
446 return thread_handle
;
450 struct ThreadMainParam
{
451 ThreadMainParam(Runnable
* runnable
, Notification
* thread_can_start
)
452 : runnable_(runnable
), thread_can_start_(thread_can_start
) {}
453 std::unique_ptr
<Runnable
> runnable_
;
455 Notification
* thread_can_start_
;
458 static DWORD WINAPI
ThreadMain(void* ptr
) {
459 // Transfers ownership.
460 std::unique_ptr
<ThreadMainParam
> param(static_cast<ThreadMainParam
*>(ptr
));
461 if (param
->thread_can_start_
!= nullptr)
462 param
->thread_can_start_
->WaitForNotification();
463 param
->runnable_
->Run();
467 // Prohibit instantiation.
468 ThreadWithParamSupport();
470 ThreadWithParamSupport(const ThreadWithParamSupport
&) = delete;
471 ThreadWithParamSupport
& operator=(const ThreadWithParamSupport
&) = delete;
476 ThreadWithParamBase::ThreadWithParamBase(Runnable
* runnable
,
477 Notification
* thread_can_start
)
479 ThreadWithParamSupport::CreateThread(runnable
, thread_can_start
)) {}
481 ThreadWithParamBase::~ThreadWithParamBase() { Join(); }
483 void ThreadWithParamBase::Join() {
484 GTEST_CHECK_(::WaitForSingleObject(thread_
.Get(), INFINITE
) == WAIT_OBJECT_0
)
485 << "Failed to join the thread with error " << ::GetLastError() << ".";
488 // Maps a thread to a set of ThreadIdToThreadLocals that have values
489 // instantiated on that thread and notifies them when the thread exits. A
490 // ThreadLocal instance is expected to persist until all threads it has
491 // values on have terminated.
492 class ThreadLocalRegistryImpl
{
494 // Registers thread_local_instance as having value on the current thread.
495 // Returns a value that can be used to identify the thread from other threads.
496 static ThreadLocalValueHolderBase
* GetValueOnCurrentThread(
497 const ThreadLocalBase
* thread_local_instance
) {
499 MemoryIsNotDeallocated memory_is_not_deallocated
;
501 DWORD current_thread
= ::GetCurrentThreadId();
502 MutexLock
lock(&mutex_
);
503 ThreadIdToThreadLocals
* const thread_to_thread_locals
=
504 GetThreadLocalsMapLocked();
505 ThreadIdToThreadLocals::iterator thread_local_pos
=
506 thread_to_thread_locals
->find(current_thread
);
507 if (thread_local_pos
== thread_to_thread_locals
->end()) {
509 thread_to_thread_locals
510 ->insert(std::make_pair(current_thread
, ThreadLocalValues()))
512 StartWatcherThreadFor(current_thread
);
514 ThreadLocalValues
& thread_local_values
= thread_local_pos
->second
;
515 ThreadLocalValues::iterator value_pos
=
516 thread_local_values
.find(thread_local_instance
);
517 if (value_pos
== thread_local_values
.end()) {
520 .insert(std::make_pair(
521 thread_local_instance
,
522 std::shared_ptr
<ThreadLocalValueHolderBase
>(
523 thread_local_instance
->NewValueForCurrentThread())))
526 return value_pos
->second
.get();
529 static void OnThreadLocalDestroyed(
530 const ThreadLocalBase
* thread_local_instance
) {
531 std::vector
<std::shared_ptr
<ThreadLocalValueHolderBase
> > value_holders
;
532 // Clean up the ThreadLocalValues data structure while holding the lock, but
533 // defer the destruction of the ThreadLocalValueHolderBases.
535 MutexLock
lock(&mutex_
);
536 ThreadIdToThreadLocals
* const thread_to_thread_locals
=
537 GetThreadLocalsMapLocked();
538 for (ThreadIdToThreadLocals::iterator it
=
539 thread_to_thread_locals
->begin();
540 it
!= thread_to_thread_locals
->end(); ++it
) {
541 ThreadLocalValues
& thread_local_values
= it
->second
;
542 ThreadLocalValues::iterator value_pos
=
543 thread_local_values
.find(thread_local_instance
);
544 if (value_pos
!= thread_local_values
.end()) {
545 value_holders
.push_back(value_pos
->second
);
546 thread_local_values
.erase(value_pos
);
547 // This 'if' can only be successful at most once, so theoretically we
548 // could break out of the loop here, but we don't bother doing so.
552 // Outside the lock, let the destructor for 'value_holders' deallocate the
553 // ThreadLocalValueHolderBases.
556 static void OnThreadExit(DWORD thread_id
) {
557 GTEST_CHECK_(thread_id
!= 0) << ::GetLastError();
558 std::vector
<std::shared_ptr
<ThreadLocalValueHolderBase
> > value_holders
;
559 // Clean up the ThreadIdToThreadLocals data structure while holding the
560 // lock, but defer the destruction of the ThreadLocalValueHolderBases.
562 MutexLock
lock(&mutex_
);
563 ThreadIdToThreadLocals
* const thread_to_thread_locals
=
564 GetThreadLocalsMapLocked();
565 ThreadIdToThreadLocals::iterator thread_local_pos
=
566 thread_to_thread_locals
->find(thread_id
);
567 if (thread_local_pos
!= thread_to_thread_locals
->end()) {
568 ThreadLocalValues
& thread_local_values
= thread_local_pos
->second
;
569 for (ThreadLocalValues::iterator value_pos
=
570 thread_local_values
.begin();
571 value_pos
!= thread_local_values
.end(); ++value_pos
) {
572 value_holders
.push_back(value_pos
->second
);
574 thread_to_thread_locals
->erase(thread_local_pos
);
577 // Outside the lock, let the destructor for 'value_holders' deallocate the
578 // ThreadLocalValueHolderBases.
582 // In a particular thread, maps a ThreadLocal object to its value.
583 typedef std::map
<const ThreadLocalBase
*,
584 std::shared_ptr
<ThreadLocalValueHolderBase
> >
586 // Stores all ThreadIdToThreadLocals having values in a thread, indexed by
588 typedef std::map
<DWORD
, ThreadLocalValues
> ThreadIdToThreadLocals
;
590 // Holds the thread id and thread handle that we pass from
591 // StartWatcherThreadFor to WatcherThreadFunc.
592 typedef std::pair
<DWORD
, HANDLE
> ThreadIdAndHandle
;
594 static void StartWatcherThreadFor(DWORD thread_id
) {
595 // The returned handle will be kept in thread_map and closed by
596 // watcher_thread in WatcherThreadFunc.
598 ::OpenThread(SYNCHRONIZE
| THREAD_QUERY_INFORMATION
, FALSE
, thread_id
);
599 GTEST_CHECK_(thread
!= nullptr);
600 // We need to pass a valid thread ID pointer into CreateThread for it
601 // to work correctly under Win98.
602 DWORD watcher_thread_id
;
603 HANDLE watcher_thread
= ::CreateThread(
604 nullptr, // Default security.
605 0, // Default stack size
606 &ThreadLocalRegistryImpl::WatcherThreadFunc
,
607 reinterpret_cast<LPVOID
>(new ThreadIdAndHandle(thread_id
, thread
)),
608 CREATE_SUSPENDED
, &watcher_thread_id
);
609 GTEST_CHECK_(watcher_thread
!= nullptr)
610 << "CreateThread failed with error " << ::GetLastError() << ".";
611 // Give the watcher thread the same priority as ours to avoid being
613 ::SetThreadPriority(watcher_thread
,
614 ::GetThreadPriority(::GetCurrentThread()));
615 ::ResumeThread(watcher_thread
);
616 ::CloseHandle(watcher_thread
);
619 // Monitors exit from a given thread and notifies those
620 // ThreadIdToThreadLocals about thread termination.
621 static DWORD WINAPI
WatcherThreadFunc(LPVOID param
) {
622 const ThreadIdAndHandle
* tah
=
623 reinterpret_cast<const ThreadIdAndHandle
*>(param
);
624 GTEST_CHECK_(::WaitForSingleObject(tah
->second
, INFINITE
) == WAIT_OBJECT_0
);
625 OnThreadExit(tah
->first
);
626 ::CloseHandle(tah
->second
);
631 // Returns map of thread local instances.
632 static ThreadIdToThreadLocals
* GetThreadLocalsMapLocked() {
635 MemoryIsNotDeallocated memory_is_not_deallocated
;
637 static ThreadIdToThreadLocals
* map
= new ThreadIdToThreadLocals();
641 // Protects access to GetThreadLocalsMapLocked() and its return value.
643 // Protects access to GetThreadMapLocked() and its return value.
644 static Mutex thread_map_mutex_
;
647 Mutex
ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex
); // NOLINT
648 Mutex
ThreadLocalRegistryImpl::thread_map_mutex_(
649 Mutex::kStaticMutex
); // NOLINT
651 ThreadLocalValueHolderBase
* ThreadLocalRegistry::GetValueOnCurrentThread(
652 const ThreadLocalBase
* thread_local_instance
) {
653 return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
654 thread_local_instance
);
657 void ThreadLocalRegistry::OnThreadLocalDestroyed(
658 const ThreadLocalBase
* thread_local_instance
) {
659 ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance
);
662 #endif // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
664 #ifdef GTEST_USES_POSIX_RE
666 // Implements RE. Currently only needed for death tests.
670 // regfree'ing an invalid regex might crash because the content
671 // of the regex is undefined. Since the regex's are essentially
672 // the same, one cannot be valid (or invalid) without the other
674 regfree(&partial_regex_
);
675 regfree(&full_regex_
);
679 // Returns true if and only if regular expression re matches the entire str.
680 bool RE::FullMatch(const char* str
, const RE
& re
) {
681 if (!re
.is_valid_
) return false;
684 return regexec(&re
.full_regex_
, str
, 1, &match
, 0) == 0;
687 // Returns true if and only if regular expression re matches a substring of
688 // str (including str itself).
689 bool RE::PartialMatch(const char* str
, const RE
& re
) {
690 if (!re
.is_valid_
) return false;
693 return regexec(&re
.partial_regex_
, str
, 1, &match
, 0) == 0;
696 // Initializes an RE from its string representation.
697 void RE::Init(const char* regex
) {
700 // Reserves enough bytes to hold the regular expression used for a
702 const size_t full_regex_len
= strlen(regex
) + 10;
703 char* const full_pattern
= new char[full_regex_len
];
705 snprintf(full_pattern
, full_regex_len
, "^(%s)$", regex
);
706 is_valid_
= regcomp(&full_regex_
, full_pattern
, REG_EXTENDED
) == 0;
707 // We want to call regcomp(&partial_regex_, ...) even if the
708 // previous expression returns false. Otherwise partial_regex_ may
709 // not be properly initialized can may cause trouble when it's
712 // Some implementation of POSIX regex (e.g. on at least some
713 // versions of Cygwin) doesn't accept the empty string as a valid
714 // regex. We change it to an equivalent form "()" to be safe.
716 const char* const partial_regex
= (*regex
== '\0') ? "()" : regex
;
717 is_valid_
= regcomp(&partial_regex_
, partial_regex
, REG_EXTENDED
) == 0;
719 EXPECT_TRUE(is_valid_
)
720 << "Regular expression \"" << regex
721 << "\" is not a valid POSIX Extended regular expression.";
723 delete[] full_pattern
;
726 #elif defined(GTEST_USES_SIMPLE_RE)
728 // Returns true if and only if ch appears anywhere in str (excluding the
729 // terminating '\0' character).
730 bool IsInSet(char ch
, const char* str
) {
731 return ch
!= '\0' && strchr(str
, ch
) != nullptr;
734 // Returns true if and only if ch belongs to the given classification.
735 // Unlike similar functions in <ctype.h>, these aren't affected by the
737 bool IsAsciiDigit(char ch
) { return '0' <= ch
&& ch
<= '9'; }
738 bool IsAsciiPunct(char ch
) {
739 return IsInSet(ch
, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
741 bool IsRepeat(char ch
) { return IsInSet(ch
, "?*+"); }
742 bool IsAsciiWhiteSpace(char ch
) { return IsInSet(ch
, " \f\n\r\t\v"); }
743 bool IsAsciiWordChar(char ch
) {
744 return ('a' <= ch
&& ch
<= 'z') || ('A' <= ch
&& ch
<= 'Z') ||
745 ('0' <= ch
&& ch
<= '9') || ch
== '_';
748 // Returns true if and only if "\\c" is a supported escape sequence.
749 bool IsValidEscape(char c
) {
750 return (IsAsciiPunct(c
) || IsInSet(c
, "dDfnrsStvwW"));
753 // Returns true if and only if the given atom (specified by escaped and
754 // pattern) matches ch. The result is undefined if the atom is invalid.
755 bool AtomMatchesChar(bool escaped
, char pattern_char
, char ch
) {
756 if (escaped
) { // "\\p" where p is pattern_char.
757 switch (pattern_char
) {
759 return IsAsciiDigit(ch
);
761 return !IsAsciiDigit(ch
);
769 return IsAsciiWhiteSpace(ch
);
771 return !IsAsciiWhiteSpace(ch
);
777 return IsAsciiWordChar(ch
);
779 return !IsAsciiWordChar(ch
);
781 return IsAsciiPunct(pattern_char
) && pattern_char
== ch
;
784 return (pattern_char
== '.' && ch
!= '\n') || pattern_char
== ch
;
787 // Helper function used by ValidateRegex() to format error messages.
788 static std::string
FormatRegexSyntaxError(const char* regex
, int index
) {
789 return (Message() << "Syntax error at index " << index
790 << " in simple regular expression \"" << regex
<< "\": ")
794 // Generates non-fatal failures and returns false if regex is invalid;
795 // otherwise returns true.
796 bool ValidateRegex(const char* regex
) {
797 if (regex
== nullptr) {
798 ADD_FAILURE() << "NULL is not a valid simple regular expression.";
802 bool is_valid
= true;
804 // True if and only if ?, *, or + can follow the previous atom.
805 bool prev_repeatable
= false;
806 for (int i
= 0; regex
[i
]; i
++) {
807 if (regex
[i
] == '\\') { // An escape sequence
809 if (regex
[i
] == '\0') {
810 ADD_FAILURE() << FormatRegexSyntaxError(regex
, i
- 1)
811 << "'\\' cannot appear at the end.";
815 if (!IsValidEscape(regex
[i
])) {
816 ADD_FAILURE() << FormatRegexSyntaxError(regex
, i
- 1)
817 << "invalid escape sequence \"\\" << regex
[i
] << "\".";
820 prev_repeatable
= true;
821 } else { // Not an escape sequence.
822 const char ch
= regex
[i
];
824 if (ch
== '^' && i
> 0) {
825 ADD_FAILURE() << FormatRegexSyntaxError(regex
, i
)
826 << "'^' can only appear at the beginning.";
828 } else if (ch
== '$' && regex
[i
+ 1] != '\0') {
829 ADD_FAILURE() << FormatRegexSyntaxError(regex
, i
)
830 << "'$' can only appear at the end.";
832 } else if (IsInSet(ch
, "()[]{}|")) {
833 ADD_FAILURE() << FormatRegexSyntaxError(regex
, i
) << "'" << ch
834 << "' is unsupported.";
836 } else if (IsRepeat(ch
) && !prev_repeatable
) {
837 ADD_FAILURE() << FormatRegexSyntaxError(regex
, i
) << "'" << ch
838 << "' can only follow a repeatable token.";
842 prev_repeatable
= !IsInSet(ch
, "^$?*+");
849 // Matches a repeated regex atom followed by a valid simple regular
850 // expression. The regex atom is defined as c if escaped is false,
851 // or \c otherwise. repeat is the repetition meta character (?, *,
852 // or +). The behavior is undefined if str contains too many
853 // characters to be indexable by size_t, in which case the test will
854 // probably time out anyway. We are fine with this limitation as
855 // std::string has it too.
856 bool MatchRepetitionAndRegexAtHead(bool escaped
, char c
, char repeat
,
857 const char* regex
, const char* str
) {
858 const size_t min_count
= (repeat
== '+') ? 1 : 0;
859 const size_t max_count
= (repeat
== '?') ? 1 : static_cast<size_t>(-1) - 1;
860 // We cannot call numeric_limits::max() as it conflicts with the
861 // max() macro on Windows.
863 for (size_t i
= 0; i
<= max_count
; ++i
) {
864 // We know that the atom matches each of the first i characters in str.
865 if (i
>= min_count
&& MatchRegexAtHead(regex
, str
+ i
)) {
866 // We have enough matches at the head, and the tail matches too.
867 // Since we only care about *whether* the pattern matches str
868 // (as opposed to *how* it matches), there is no need to find a
872 if (str
[i
] == '\0' || !AtomMatchesChar(escaped
, c
, str
[i
])) return false;
877 // Returns true if and only if regex matches a prefix of str. regex must
878 // be a valid simple regular expression and not start with "^", or the
879 // result is undefined.
880 bool MatchRegexAtHead(const char* regex
, const char* str
) {
881 if (*regex
== '\0') // An empty regex matches a prefix of anything.
884 // "$" only matches the end of a string. Note that regex being
885 // valid guarantees that there's nothing after "$" in it.
886 if (*regex
== '$') return *str
== '\0';
888 // Is the first thing in regex an escape sequence?
889 const bool escaped
= *regex
== '\\';
890 if (escaped
) ++regex
;
891 if (IsRepeat(regex
[1])) {
892 // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
893 // here's an indirect recursion. It terminates as the regex gets
894 // shorter in each recursion.
895 return MatchRepetitionAndRegexAtHead(escaped
, regex
[0], regex
[1], regex
+ 2,
898 // regex isn't empty, isn't "$", and doesn't start with a
899 // repetition. We match the first atom of regex with the first
900 // character of str and recurse.
901 return (*str
!= '\0') && AtomMatchesChar(escaped
, *regex
, *str
) &&
902 MatchRegexAtHead(regex
+ 1, str
+ 1);
906 // Returns true if and only if regex matches any substring of str. regex must
907 // be a valid simple regular expression, or the result is undefined.
909 // The algorithm is recursive, but the recursion depth doesn't exceed
910 // the regex length, so we won't need to worry about running out of
911 // stack space normally. In rare cases the time complexity can be
912 // exponential with respect to the regex length + the string length,
913 // but usually it's must faster (often close to linear).
914 bool MatchRegexAnywhere(const char* regex
, const char* str
) {
915 if (regex
== nullptr || str
== nullptr) return false;
917 if (*regex
== '^') return MatchRegexAtHead(regex
+ 1, str
);
919 // A successful match can be anywhere in str.
921 if (MatchRegexAtHead(regex
, str
)) return true;
922 } while (*str
++ != '\0');
926 // Implements the RE class.
930 // Returns true if and only if regular expression re matches the entire str.
931 bool RE::FullMatch(const char* str
, const RE
& re
) {
932 return re
.is_valid_
&& MatchRegexAnywhere(re
.full_pattern_
.c_str(), str
);
935 // Returns true if and only if regular expression re matches a substring of
936 // str (including str itself).
937 bool RE::PartialMatch(const char* str
, const RE
& re
) {
938 return re
.is_valid_
&& MatchRegexAnywhere(re
.pattern_
.c_str(), str
);
941 // Initializes an RE from its string representation.
942 void RE::Init(const char* regex
) {
943 full_pattern_
.clear();
946 if (regex
!= nullptr) {
950 is_valid_
= ValidateRegex(regex
);
952 // No need to calculate the full pattern when the regex is invalid.
956 // Reserves enough bytes to hold the regular expression used for a
957 // full match: we need space to prepend a '^' and append a '$'.
958 full_pattern_
.reserve(pattern_
.size() + 2);
960 if (pattern_
.empty() || pattern_
.front() != '^') {
961 full_pattern_
.push_back('^'); // Makes sure full_pattern_ starts with '^'.
964 full_pattern_
.append(pattern_
);
966 if (pattern_
.empty() || pattern_
.back() != '$') {
967 full_pattern_
.push_back('$'); // Makes sure full_pattern_ ends with '$'.
971 #endif // GTEST_USES_POSIX_RE
973 const char kUnknownFile
[] = "unknown file";
975 // Formats a source file path and a line number as they would appear
976 // in an error message from the compiler used to compile this code.
977 GTEST_API_ ::std::string
FormatFileLocation(const char* file
, int line
) {
978 const std::string
file_name(file
== nullptr ? kUnknownFile
: file
);
981 return file_name
+ ":";
984 return file_name
+ "(" + StreamableToString(line
) + "):";
986 return file_name
+ ":" + StreamableToString(line
) + ":";
990 // Formats a file location for compiler-independent XML output.
991 // Although this function is not platform dependent, we put it next to
992 // FormatFileLocation in order to contrast the two functions.
993 // Note that FormatCompilerIndependentFileLocation() does NOT append colon
994 // to the file location it produces, unlike FormatFileLocation().
995 GTEST_API_ ::std::string
FormatCompilerIndependentFileLocation(const char* file
,
997 const std::string
file_name(file
== nullptr ? kUnknownFile
: file
);
1002 return file_name
+ ":" + StreamableToString(line
);
1005 GTestLog::GTestLog(GTestLogSeverity severity
, const char* file
, int line
)
1006 : severity_(severity
) {
1007 const char* const marker
= severity
== GTEST_INFO
? "[ INFO ]"
1008 : severity
== GTEST_WARNING
? "[WARNING]"
1009 : severity
== GTEST_ERROR
? "[ ERROR ]"
1011 GetStream() << ::std::endl
1012 << marker
<< " " << FormatFileLocation(file
, line
).c_str()
1016 // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
1017 GTestLog::~GTestLog() {
1018 GetStream() << ::std::endl
;
1019 if (severity_
== GTEST_FATAL
) {
1025 // Disable Microsoft deprecation warnings for POSIX functions called from
1026 // this class (creat, dup, dup2, and close)
1027 GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
1029 #if GTEST_HAS_STREAM_REDIRECTION
1031 // Object that captures an output stream (stdout/stderr).
1032 class CapturedStream
{
1034 // The ctor redirects the stream to a temporary file.
1035 explicit CapturedStream(int fd
) : fd_(fd
), uncaptured_fd_(dup(fd
)) {
1036 #ifdef GTEST_OS_WINDOWS
1037 char temp_dir_path
[MAX_PATH
+ 1] = {'\0'}; // NOLINT
1038 char temp_file_path
[MAX_PATH
+ 1] = {'\0'}; // NOLINT
1040 ::GetTempPathA(sizeof(temp_dir_path
), temp_dir_path
);
1041 const UINT success
= ::GetTempFileNameA(temp_dir_path
, "gtest_redir",
1042 0, // Generate unique file name.
1044 GTEST_CHECK_(success
!= 0)
1045 << "Unable to create a temporary file in " << temp_dir_path
;
1046 const int captured_fd
= creat(temp_file_path
, _S_IREAD
| _S_IWRITE
);
1047 GTEST_CHECK_(captured_fd
!= -1)
1048 << "Unable to open temporary file " << temp_file_path
;
1049 filename_
= temp_file_path
;
1051 // There's no guarantee that a test has write access to the current
1052 // directory, so we create the temporary file in a temporary directory.
1053 std::string name_template
;
1055 #ifdef GTEST_OS_LINUX_ANDROID
1056 // Note: Android applications are expected to call the framework's
1057 // Context.getExternalStorageDirectory() method through JNI to get
1058 // the location of the world-writable SD Card directory. However,
1059 // this requires a Context handle, which cannot be retrieved
1060 // globally from native code. Doing so also precludes running the
1061 // code as part of a regular standalone executable, which doesn't
1062 // run in a Dalvik process (e.g. when running it through 'adb shell').
1064 // The location /data/local/tmp is directly accessible from native code.
1065 // '/sdcard' and other variants cannot be relied on, as they are not
1066 // guaranteed to be mounted, or may have a delay in mounting.
1067 name_template
= "/data/local/tmp/";
1068 #elif defined(GTEST_OS_IOS)
1069 char user_temp_dir
[PATH_MAX
+ 1];
1071 // Documented alternative to NSTemporaryDirectory() (for obtaining creating
1072 // a temporary directory) at
1073 // https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
1075 // _CS_DARWIN_USER_TEMP_DIR (as well as _CS_DARWIN_USER_CACHE_DIR) is not
1076 // documented in the confstr() man page at
1077 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/confstr.3.html#//apple_ref/doc/man/3/confstr
1078 // but are still available, according to the WebKit patches at
1079 // https://trac.webkit.org/changeset/262004/webkit
1080 // https://trac.webkit.org/changeset/263705/webkit
1082 // The confstr() implementation falls back to getenv("TMPDIR"). See
1083 // https://opensource.apple.com/source/Libc/Libc-1439.100.3/gen/confstr.c.auto.html
1084 ::confstr(_CS_DARWIN_USER_TEMP_DIR
, user_temp_dir
, sizeof(user_temp_dir
));
1086 name_template
= user_temp_dir
;
1087 if (name_template
.back() != GTEST_PATH_SEP_
[0])
1088 name_template
.push_back(GTEST_PATH_SEP_
[0]);
1090 name_template
= "/tmp/";
1092 name_template
.append("gtest_captured_stream.XXXXXX");
1094 // mkstemp() modifies the string bytes in place, and does not go beyond the
1095 // string's length. This results in well-defined behavior in C++17.
1097 // The const_cast is needed below C++17. The constraints on std::string
1098 // implementations in C++11 and above make assumption behind the const_cast
1100 const int captured_fd
= ::mkstemp(const_cast<char*>(name_template
.data()));
1101 if (captured_fd
== -1) {
1103 << "Failed to create tmp file " << name_template
1104 << " for test; does the test have access to the /tmp directory?";
1106 filename_
= std::move(name_template
);
1107 #endif // GTEST_OS_WINDOWS
1109 dup2(captured_fd
, fd_
);
1113 ~CapturedStream() { remove(filename_
.c_str()); }
1115 std::string
GetCapturedString() {
1116 if (uncaptured_fd_
!= -1) {
1117 // Restores the original stream.
1119 dup2(uncaptured_fd_
, fd_
);
1120 close(uncaptured_fd_
);
1121 uncaptured_fd_
= -1;
1124 FILE* const file
= posix::FOpen(filename_
.c_str(), "r");
1125 if (file
== nullptr) {
1126 GTEST_LOG_(FATAL
) << "Failed to open tmp file " << filename_
1127 << " for capturing stream.";
1129 const std::string content
= ReadEntireFile(file
);
1130 posix::FClose(file
);
1135 const int fd_
; // A stream to capture.
1137 // Name of the temporary file holding the stderr output.
1138 ::std::string filename_
;
1140 CapturedStream(const CapturedStream
&) = delete;
1141 CapturedStream
& operator=(const CapturedStream
&) = delete;
1144 GTEST_DISABLE_MSC_DEPRECATED_POP_()
1146 static CapturedStream
* g_captured_stderr
= nullptr;
1147 static CapturedStream
* g_captured_stdout
= nullptr;
1149 // Starts capturing an output stream (stdout/stderr).
1150 static void CaptureStream(int fd
, const char* stream_name
,
1151 CapturedStream
** stream
) {
1152 if (*stream
!= nullptr) {
1153 GTEST_LOG_(FATAL
) << "Only one " << stream_name
1154 << " capturer can exist at a time.";
1156 *stream
= new CapturedStream(fd
);
1159 // Stops capturing the output stream and returns the captured string.
1160 static std::string
GetCapturedStream(CapturedStream
** captured_stream
) {
1161 const std::string content
= (*captured_stream
)->GetCapturedString();
1163 delete *captured_stream
;
1164 *captured_stream
= nullptr;
1169 #if defined(_MSC_VER) || defined(__BORLANDC__)
1170 // MSVC and C++Builder do not provide a definition of STDERR_FILENO.
1171 const int kStdOutFileno
= 1;
1172 const int kStdErrFileno
= 2;
1174 const int kStdOutFileno
= STDOUT_FILENO
;
1175 const int kStdErrFileno
= STDERR_FILENO
;
1176 #endif // defined(_MSC_VER) || defined(__BORLANDC__)
1178 // Starts capturing stdout.
1179 void CaptureStdout() {
1180 CaptureStream(kStdOutFileno
, "stdout", &g_captured_stdout
);
1183 // Starts capturing stderr.
1184 void CaptureStderr() {
1185 CaptureStream(kStdErrFileno
, "stderr", &g_captured_stderr
);
1188 // Stops capturing stdout and returns the captured string.
1189 std::string
GetCapturedStdout() {
1190 return GetCapturedStream(&g_captured_stdout
);
1193 // Stops capturing stderr and returns the captured string.
1194 std::string
GetCapturedStderr() {
1195 return GetCapturedStream(&g_captured_stderr
);
1198 #endif // GTEST_HAS_STREAM_REDIRECTION
1200 size_t GetFileSize(FILE* file
) {
1201 fseek(file
, 0, SEEK_END
);
1202 return static_cast<size_t>(ftell(file
));
1205 std::string
ReadEntireFile(FILE* file
) {
1206 const size_t file_size
= GetFileSize(file
);
1207 char* const buffer
= new char[file_size
];
1209 size_t bytes_last_read
= 0; // # of bytes read in the last fread()
1210 size_t bytes_read
= 0; // # of bytes read so far
1212 fseek(file
, 0, SEEK_SET
);
1214 // Keeps reading the file until we cannot read further or the
1215 // pre-determined file size is reached.
1218 fread(buffer
+ bytes_read
, 1, file_size
- bytes_read
, file
);
1219 bytes_read
+= bytes_last_read
;
1220 } while (bytes_last_read
> 0 && bytes_read
< file_size
);
1222 const std::string
content(buffer
, bytes_read
);
1228 #ifdef GTEST_HAS_DEATH_TEST
1229 static const std::vector
<std::string
>* g_injected_test_argvs
=
1232 std::vector
<std::string
> GetInjectableArgvs() {
1233 if (g_injected_test_argvs
!= nullptr) {
1234 return *g_injected_test_argvs
;
1239 void SetInjectableArgvs(const std::vector
<std::string
>* new_argvs
) {
1240 if (g_injected_test_argvs
!= new_argvs
) delete g_injected_test_argvs
;
1241 g_injected_test_argvs
= new_argvs
;
1244 void SetInjectableArgvs(const std::vector
<std::string
>& new_argvs
) {
1246 new std::vector
<std::string
>(new_argvs
.begin(), new_argvs
.end()));
1249 void ClearInjectableArgvs() {
1250 delete g_injected_test_argvs
;
1251 g_injected_test_argvs
= nullptr;
1253 #endif // GTEST_HAS_DEATH_TEST
1255 #ifdef GTEST_OS_WINDOWS_MOBILE
1259 TerminateProcess(GetCurrentProcess(), 1);
1261 } // namespace posix
1262 #endif // GTEST_OS_WINDOWS_MOBILE
1264 // Returns the name of the environment variable corresponding to the
1265 // given flag. For example, FlagToEnvVar("foo") will return
1266 // "GTEST_FOO" in the open-source version.
1267 static std::string
FlagToEnvVar(const char* flag
) {
1268 const std::string full_flag
=
1269 (Message() << GTEST_FLAG_PREFIX_
<< flag
).GetString();
1272 for (size_t i
= 0; i
!= full_flag
.length(); i
++) {
1273 env_var
<< ToUpper(full_flag
.c_str()[i
]);
1276 return env_var
.GetString();
1279 // Parses 'str' for a 32-bit signed integer. If successful, writes
1280 // the result to *value and returns true; otherwise leaves *value
1281 // unchanged and returns false.
1282 bool ParseInt32(const Message
& src_text
, const char* str
, int32_t* value
) {
1283 // Parses the environment variable as a decimal integer.
1284 char* end
= nullptr;
1285 const long long_value
= strtol(str
, &end
, 10); // NOLINT
1287 // Has strtol() consumed all characters in the string?
1289 // No - an invalid character was encountered.
1291 msg
<< "WARNING: " << src_text
1292 << " is expected to be a 32-bit integer, but actually"
1293 << " has value \"" << str
<< "\".\n";
1294 printf("%s", msg
.GetString().c_str());
1299 // Is the parsed value in the range of an int32_t?
1300 const auto result
= static_cast<int32_t>(long_value
);
1301 if (long_value
== LONG_MAX
|| long_value
== LONG_MIN
||
1302 // The parsed value overflows as a long. (strtol() returns
1303 // LONG_MAX or LONG_MIN when the input overflows.)
1304 result
!= long_value
1305 // The parsed value overflows as an int32_t.
1308 msg
<< "WARNING: " << src_text
1309 << " is expected to be a 32-bit integer, but actually"
1310 << " has value " << str
<< ", which overflows.\n";
1311 printf("%s", msg
.GetString().c_str());
1320 // Reads and returns the Boolean environment variable corresponding to
1321 // the given flag; if it's not set, returns default_value.
1323 // The value is considered true if and only if it's not "0".
1324 bool BoolFromGTestEnv(const char* flag
, bool default_value
) {
1325 #if defined(GTEST_GET_BOOL_FROM_ENV_)
1326 return GTEST_GET_BOOL_FROM_ENV_(flag
, default_value
);
1328 const std::string env_var
= FlagToEnvVar(flag
);
1329 const char* const string_value
= posix::GetEnv(env_var
.c_str());
1330 return string_value
== nullptr ? default_value
1331 : strcmp(string_value
, "0") != 0;
1332 #endif // defined(GTEST_GET_BOOL_FROM_ENV_)
1335 // Reads and returns a 32-bit integer stored in the environment
1336 // variable corresponding to the given flag; if it isn't set or
1337 // doesn't represent a valid 32-bit integer, returns default_value.
1338 int32_t Int32FromGTestEnv(const char* flag
, int32_t default_value
) {
1339 #if defined(GTEST_GET_INT32_FROM_ENV_)
1340 return GTEST_GET_INT32_FROM_ENV_(flag
, default_value
);
1342 const std::string env_var
= FlagToEnvVar(flag
);
1343 const char* const string_value
= posix::GetEnv(env_var
.c_str());
1344 if (string_value
== nullptr) {
1345 // The environment variable is not set.
1346 return default_value
;
1349 int32_t result
= default_value
;
1350 if (!ParseInt32(Message() << "Environment variable " << env_var
, string_value
,
1352 printf("The default value %s is used.\n",
1353 (Message() << default_value
).GetString().c_str());
1355 return default_value
;
1359 #endif // defined(GTEST_GET_INT32_FROM_ENV_)
1362 // As a special case for the 'output' flag, if GTEST_OUTPUT is not
1363 // set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
1364 // system. The value of XML_OUTPUT_FILE is a filename without the
1365 // "xml:" prefix of GTEST_OUTPUT.
1366 // Note that this is meant to be called at the call site so it does
1367 // not check that the flag is 'output'
1368 // In essence this checks an env variable called XML_OUTPUT_FILE
1369 // and if it is set we prepend "xml:" to its value, if it not set we return ""
1370 std::string
OutputFlagAlsoCheckEnvVar() {
1371 std::string default_value_for_output_flag
= "";
1372 const char* xml_output_file_env
= posix::GetEnv("XML_OUTPUT_FILE");
1373 if (nullptr != xml_output_file_env
) {
1374 default_value_for_output_flag
= std::string("xml:") + xml_output_file_env
;
1376 return default_value_for_output_flag
;
1379 // Reads and returns the string environment variable corresponding to
1380 // the given flag; if it's not set, returns default_value.
1381 const char* StringFromGTestEnv(const char* flag
, const char* default_value
) {
1382 #if defined(GTEST_GET_STRING_FROM_ENV_)
1383 return GTEST_GET_STRING_FROM_ENV_(flag
, default_value
);
1385 const std::string env_var
= FlagToEnvVar(flag
);
1386 const char* const value
= posix::GetEnv(env_var
.c_str());
1387 return value
== nullptr ? default_value
: value
;
1388 #endif // defined(GTEST_GET_STRING_FROM_ENV_)
1391 } // namespace internal
1392 } // namespace testing