1 // Copyright 2008, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
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
13 // distribution.
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.
17 //
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.
29 //
30 // Author: wan@google.com (Zhanyong Wan)
31
32 #include "gtest/internal/gtest-port.h"
33
34 #include <limits.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38
39 #if GTEST_OS_WINDOWS
40 # include <windows.h>
41 # include <io.h>
42 # include <sys/stat.h>
43 # include <map> // Used in ThreadLocal.
44 #else
45 # include <unistd.h>
46 #endif // GTEST_OS_WINDOWS
47
48 #if GTEST_OS_MAC
49 # include <mach/mach_init.h>
50 # include <mach/task.h>
51 # include <mach/vm_map.h>
52 #endif // GTEST_OS_MAC
53
54 #if GTEST_OS_QNX
55 # include <devctl.h>
56 # include <sys/procfs.h>
57 #endif // GTEST_OS_QNX
58
59 #include "gtest/gtest-spi.h"
60 #include "gtest/gtest-message.h"
61 #include "gtest/internal/gtest-internal.h"
62 #include "gtest/internal/gtest-string.h"
63
64 // Indicates that this translation unit is part of Google Test's
65 // implementation. It must come before gtest-internal-inl.h is
66 // included, or there will be a compiler error. This trick is to
67 // prevent a user from accidentally including gtest-internal-inl.h in
68 // his code.
69 #define GTEST_IMPLEMENTATION_ 1
70 #include "src/gtest-internal-inl.h"
71 #undef GTEST_IMPLEMENTATION_
72
73 namespace testing {
74 namespace internal {
75
76 #if defined(_MSC_VER) || defined(__BORLANDC__)
77 // MSVC and C++Builder do not provide a definition of STDERR_FILENO.
78 const int kStdOutFileno = 1;
79 const int kStdErrFileno = 2;
80 #else
81 const int kStdOutFileno = STDOUT_FILENO;
82 const int kStdErrFileno = STDERR_FILENO;
83 #endif // _MSC_VER
84
85 #if GTEST_OS_MAC
86
87 // Returns the number of threads running in the process, or 0 to indicate that
88 // we cannot detect it.
GetThreadCount()89 size_t GetThreadCount() {
90 const task_t task = mach_task_self();
91 mach_msg_type_number_t thread_count;
92 thread_act_array_t thread_list;
93 const kern_return_t status = task_threads(task, &thread_list, &thread_count);
94 if (status == KERN_SUCCESS) {
95 // task_threads allocates resources in thread_list and we need to free them
96 // to avoid leaks.
97 vm_deallocate(task,
98 reinterpret_cast<vm_address_t>(thread_list),
99 sizeof(thread_t) * thread_count);
100 return static_cast<size_t>(thread_count);
101 } else {
102 return 0;
103 }
104 }
105
106 #elif GTEST_OS_QNX
107
108 // Returns the number of threads running in the process, or 0 to indicate that
109 // we cannot detect it.
GetThreadCount()110 size_t GetThreadCount() {
111 const int fd = open("/proc/self/as", O_RDONLY);
112 if (fd < 0) {
113 return 0;
114 }
115 procfs_info process_info;
116 const int status =
117 devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
118 close(fd);
119 if (status == EOK) {
120 return static_cast<size_t>(process_info.num_threads);
121 } else {
122 return 0;
123 }
124 }
125
126 #else
127
GetThreadCount()128 size_t GetThreadCount() {
129 // There's no portable way to detect the number of threads, so we just
130 // return 0 to indicate that we cannot detect it.
131 return 0;
132 }
133
134 #endif // GTEST_OS_MAC
135
136 #if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
137
SleepMilliseconds(int n)138 void SleepMilliseconds(int n) {
139 ::Sleep(n);
140 }
141
AutoHandle()142 AutoHandle::AutoHandle()
143 : handle_(INVALID_HANDLE_VALUE) {}
144
AutoHandle(Handle handle)145 AutoHandle::AutoHandle(Handle handle)
146 : handle_(handle) {}
147
~AutoHandle()148 AutoHandle::~AutoHandle() {
149 Reset();
150 }
151
Get() const152 AutoHandle::Handle AutoHandle::Get() const {
153 return handle_;
154 }
155
Reset()156 void AutoHandle::Reset() {
157 Reset(INVALID_HANDLE_VALUE);
158 }
159
Reset(HANDLE handle)160 void AutoHandle::Reset(HANDLE handle) {
161 // Resetting with the same handle we already own is invalid.
162 if (handle_ != handle) {
163 if (IsCloseable()) {
164 ::CloseHandle(handle_);
165 }
166 handle_ = handle;
167 } else {
168 GTEST_CHECK_(!IsCloseable())
169 << "Resetting a valid handle to itself is likely a programmer error "
170 "and thus not allowed.";
171 }
172 }
173
IsCloseable() const174 bool AutoHandle::IsCloseable() const {
175 // Different Windows APIs may use either of these values to represent an
176 // invalid handle.
177 return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE;
178 }
179
Notification()180 Notification::Notification()
181 : event_(::CreateEvent(NULL, // Default security attributes.
182 TRUE, // Do not reset automatically.
183 FALSE, // Initially unset.
184 NULL)) { // Anonymous event.
185 GTEST_CHECK_(event_.Get() != NULL);
186 }
187
Notify()188 void Notification::Notify() {
189 GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
190 }
191
WaitForNotification()192 void Notification::WaitForNotification() {
193 GTEST_CHECK_(
194 ::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
195 }
196
Mutex()197 Mutex::Mutex()
198 : type_(kDynamic),
199 owner_thread_id_(0),
200 critical_section_init_phase_(0),
201 critical_section_(new CRITICAL_SECTION) {
202 ::InitializeCriticalSection(critical_section_);
203 }
204
~Mutex()205 Mutex::~Mutex() {
206 // Static mutexes are leaked intentionally. It is not thread-safe to try
207 // to clean them up.
208 // TODO(yukawa): Switch to Slim Reader/Writer (SRW) Locks, which requires
209 // nothing to clean it up but is available only on Vista and later.
210 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937.aspx
211 if (type_ == kDynamic) {
212 ::DeleteCriticalSection(critical_section_);
213 delete critical_section_;
214 critical_section_ = NULL;
215 }
216 }
217
Lock()218 void Mutex::Lock() {
219 ThreadSafeLazyInit();
220 ::EnterCriticalSection(critical_section_);
221 owner_thread_id_ = ::GetCurrentThreadId();
222 }
223
Unlock()224 void Mutex::Unlock() {
225 ThreadSafeLazyInit();
226 // We don't protect writing to owner_thread_id_ here, as it's the
227 // caller's responsibility to ensure that the current thread holds the
228 // mutex when this is called.
229 owner_thread_id_ = 0;
230 ::LeaveCriticalSection(critical_section_);
231 }
232
233 // Does nothing if the current thread holds the mutex. Otherwise, crashes
234 // with high probability.
AssertHeld()235 void Mutex::AssertHeld() {
236 ThreadSafeLazyInit();
237 GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
238 << "The current thread is not holding the mutex @" << this;
239 }
240
241 // Initializes owner_thread_id_ and critical_section_ in static mutexes.
ThreadSafeLazyInit()242 void Mutex::ThreadSafeLazyInit() {
243 // Dynamic mutexes are initialized in the constructor.
244 if (type_ == kStatic) {
245 switch (
246 ::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
247 case 0:
248 // If critical_section_init_phase_ was 0 before the exchange, we
249 // are the first to test it and need to perform the initialization.
250 owner_thread_id_ = 0;
251 critical_section_ = new CRITICAL_SECTION;
252 ::InitializeCriticalSection(critical_section_);
253 // Updates the critical_section_init_phase_ to 2 to signal
254 // initialization complete.
255 GTEST_CHECK_(::InterlockedCompareExchange(
256 &critical_section_init_phase_, 2L, 1L) ==
257 1L);
258 break;
259 case 1:
260 // Somebody else is already initializing the mutex; spin until they
261 // are done.
262 while (::InterlockedCompareExchange(&critical_section_init_phase_,
263 2L,
264 2L) != 2L) {
265 // Possibly yields the rest of the thread's time slice to other
266 // threads.
267 ::Sleep(0);
268 }
269 break;
270
271 case 2:
272 break; // The mutex is already initialized and ready for use.
273
274 default:
275 GTEST_CHECK_(false)
276 << "Unexpected value of critical_section_init_phase_ "
277 << "while initializing a static mutex.";
278 }
279 }
280 }
281
282 namespace {
283
284 class ThreadWithParamSupport : public ThreadWithParamBase {
285 public:
CreateThread(Runnable * runnable,Notification * thread_can_start)286 static HANDLE CreateThread(Runnable* runnable,
287 Notification* thread_can_start) {
288 ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
289 DWORD thread_id;
290 // TODO(yukawa): Consider to use _beginthreadex instead.
291 HANDLE thread_handle = ::CreateThread(
292 NULL, // Default security.
293 0, // Default stack size.
294 &ThreadWithParamSupport::ThreadMain,
295 param, // Parameter to ThreadMainStatic
296 0x0, // Default creation flags.
297 &thread_id); // Need a valid pointer for the call to work under Win98.
298 GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error "
299 << ::GetLastError() << ".";
300 if (thread_handle == NULL) {
301 delete param;
302 }
303 return thread_handle;
304 }
305
306 private:
307 struct ThreadMainParam {
ThreadMainParamtesting::internal::__anon7be672a40111::ThreadWithParamSupport::ThreadMainParam308 ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
309 : runnable_(runnable),
310 thread_can_start_(thread_can_start) {
311 }
312 scoped_ptr<Runnable> runnable_;
313 // Does not own.
314 Notification* thread_can_start_;
315 };
316
ThreadMain(void * ptr)317 static DWORD WINAPI ThreadMain(void* ptr) {
318 // Transfers ownership.
319 scoped_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
320 if (param->thread_can_start_ != NULL)
321 param->thread_can_start_->WaitForNotification();
322 param->runnable_->Run();
323 return 0;
324 }
325
326 // Prohibit instantiation.
327 ThreadWithParamSupport();
328
329 GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport);
330 };
331
332 } // namespace
333
ThreadWithParamBase(Runnable * runnable,Notification * thread_can_start)334 ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
335 Notification* thread_can_start)
336 : thread_(ThreadWithParamSupport::CreateThread(runnable,
337 thread_can_start)) {
338 }
339
~ThreadWithParamBase()340 ThreadWithParamBase::~ThreadWithParamBase() {
341 Join();
342 }
343
Join()344 void ThreadWithParamBase::Join() {
345 GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
346 << "Failed to join the thread with error " << ::GetLastError() << ".";
347 }
348
349 // Maps a thread to a set of ThreadIdToThreadLocals that have values
350 // instantiated on that thread and notifies them when the thread exits. A
351 // ThreadLocal instance is expected to persist until all threads it has
352 // values on have terminated.
353 class ThreadLocalRegistryImpl {
354 public:
355 // Registers thread_local_instance as having value on the current thread.
356 // Returns a value that can be used to identify the thread from other threads.
GetValueOnCurrentThread(const ThreadLocalBase * thread_local_instance)357 static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
358 const ThreadLocalBase* thread_local_instance) {
359 DWORD current_thread = ::GetCurrentThreadId();
360 MutexLock lock(&mutex_);
361 ThreadIdToThreadLocals* const thread_to_thread_locals =
362 GetThreadLocalsMapLocked();
363 ThreadIdToThreadLocals::iterator thread_local_pos =
364 thread_to_thread_locals->find(current_thread);
365 if (thread_local_pos == thread_to_thread_locals->end()) {
366 thread_local_pos = thread_to_thread_locals->insert(
367 std::make_pair(current_thread, ThreadLocalValues())).first;
368 StartWatcherThreadFor(current_thread);
369 }
370 ThreadLocalValues& thread_local_values = thread_local_pos->second;
371 ThreadLocalValues::iterator value_pos =
372 thread_local_values.find(thread_local_instance);
373 if (value_pos == thread_local_values.end()) {
374 value_pos =
375 thread_local_values
376 .insert(std::make_pair(
377 thread_local_instance,
378 linked_ptr<ThreadLocalValueHolderBase>(
379 thread_local_instance->NewValueForCurrentThread())))
380 .first;
381 }
382 return value_pos->second.get();
383 }
384
OnThreadLocalDestroyed(const ThreadLocalBase * thread_local_instance)385 static void OnThreadLocalDestroyed(
386 const ThreadLocalBase* thread_local_instance) {
387 std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
388 // Clean up the ThreadLocalValues data structure while holding the lock, but
389 // defer the destruction of the ThreadLocalValueHolderBases.
390 {
391 MutexLock lock(&mutex_);
392 ThreadIdToThreadLocals* const thread_to_thread_locals =
393 GetThreadLocalsMapLocked();
394 for (ThreadIdToThreadLocals::iterator it =
395 thread_to_thread_locals->begin();
396 it != thread_to_thread_locals->end();
397 ++it) {
398 ThreadLocalValues& thread_local_values = it->second;
399 ThreadLocalValues::iterator value_pos =
400 thread_local_values.find(thread_local_instance);
401 if (value_pos != thread_local_values.end()) {
402 value_holders.push_back(value_pos->second);
403 thread_local_values.erase(value_pos);
404 // This 'if' can only be successful at most once, so theoretically we
405 // could break out of the loop here, but we don't bother doing so.
406 }
407 }
408 }
409 // Outside the lock, let the destructor for 'value_holders' deallocate the
410 // ThreadLocalValueHolderBases.
411 }
412
OnThreadExit(DWORD thread_id)413 static void OnThreadExit(DWORD thread_id) {
414 GTEST_CHECK_(thread_id != 0) << ::GetLastError();
415 std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
416 // Clean up the ThreadIdToThreadLocals data structure while holding the
417 // lock, but defer the destruction of the ThreadLocalValueHolderBases.
418 {
419 MutexLock lock(&mutex_);
420 ThreadIdToThreadLocals* const thread_to_thread_locals =
421 GetThreadLocalsMapLocked();
422 ThreadIdToThreadLocals::iterator thread_local_pos =
423 thread_to_thread_locals->find(thread_id);
424 if (thread_local_pos != thread_to_thread_locals->end()) {
425 ThreadLocalValues& thread_local_values = thread_local_pos->second;
426 for (ThreadLocalValues::iterator value_pos =
427 thread_local_values.begin();
428 value_pos != thread_local_values.end();
429 ++value_pos) {
430 value_holders.push_back(value_pos->second);
431 }
432 thread_to_thread_locals->erase(thread_local_pos);
433 }
434 }
435 // Outside the lock, let the destructor for 'value_holders' deallocate the
436 // ThreadLocalValueHolderBases.
437 }
438
439 private:
440 // In a particular thread, maps a ThreadLocal object to its value.
441 typedef std::map<const ThreadLocalBase*,
442 linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues;
443 // Stores all ThreadIdToThreadLocals having values in a thread, indexed by
444 // thread's ID.
445 typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
446
447 // Holds the thread id and thread handle that we pass from
448 // StartWatcherThreadFor to WatcherThreadFunc.
449 typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
450
StartWatcherThreadFor(DWORD thread_id)451 static void StartWatcherThreadFor(DWORD thread_id) {
452 // The returned handle will be kept in thread_map and closed by
453 // watcher_thread in WatcherThreadFunc.
454 HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
455 FALSE,
456 thread_id);
457 GTEST_CHECK_(thread != NULL);
458 // We need to to pass a valid thread ID pointer into CreateThread for it
459 // to work correctly under Win98.
460 DWORD watcher_thread_id;
461 HANDLE watcher_thread = ::CreateThread(
462 NULL, // Default security.
463 0, // Default stack size
464 &ThreadLocalRegistryImpl::WatcherThreadFunc,
465 reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
466 CREATE_SUSPENDED,
467 &watcher_thread_id);
468 GTEST_CHECK_(watcher_thread != NULL);
469 // Give the watcher thread the same priority as ours to avoid being
470 // blocked by it.
471 ::SetThreadPriority(watcher_thread,
472 ::GetThreadPriority(::GetCurrentThread()));
473 ::ResumeThread(watcher_thread);
474 ::CloseHandle(watcher_thread);
475 }
476
477 // Monitors exit from a given thread and notifies those
478 // ThreadIdToThreadLocals about thread termination.
WatcherThreadFunc(LPVOID param)479 static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
480 const ThreadIdAndHandle* tah =
481 reinterpret_cast<const ThreadIdAndHandle*>(param);
482 GTEST_CHECK_(
483 ::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
484 OnThreadExit(tah->first);
485 ::CloseHandle(tah->second);
486 delete tah;
487 return 0;
488 }
489
490 // Returns map of thread local instances.
GetThreadLocalsMapLocked()491 static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
492 mutex_.AssertHeld();
493 static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals;
494 return map;
495 }
496
497 // Protects access to GetThreadLocalsMapLocked() and its return value.
498 static Mutex mutex_;
499 // Protects access to GetThreadMapLocked() and its return value.
500 static Mutex thread_map_mutex_;
501 };
502
503 Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
504 Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);
505
GetValueOnCurrentThread(const ThreadLocalBase * thread_local_instance)506 ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
507 const ThreadLocalBase* thread_local_instance) {
508 return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
509 thread_local_instance);
510 }
511
OnThreadLocalDestroyed(const ThreadLocalBase * thread_local_instance)512 void ThreadLocalRegistry::OnThreadLocalDestroyed(
513 const ThreadLocalBase* thread_local_instance) {
514 ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
515 }
516
517 #endif // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
518
519 #if GTEST_USES_POSIX_RE
520
521 // Implements RE. Currently only needed for death tests.
522
~RE()523 RE::~RE() {
524 if (is_valid_) {
525 // regfree'ing an invalid regex might crash because the content
526 // of the regex is undefined. Since the regex's are essentially
527 // the same, one cannot be valid (or invalid) without the other
528 // being so too.
529 regfree(&partial_regex_);
530 regfree(&full_regex_);
531 }
532 free(const_cast<char*>(pattern_));
533 }
534
535 // Returns true iff regular expression re matches the entire str.
FullMatch(const char * str,const RE & re)536 bool RE::FullMatch(const char* str, const RE& re) {
537 if (!re.is_valid_) return false;
538
539 regmatch_t match;
540 return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
541 }
542
543 // Returns true iff regular expression re matches a substring of str
544 // (including str itself).
PartialMatch(const char * str,const RE & re)545 bool RE::PartialMatch(const char* str, const RE& re) {
546 if (!re.is_valid_) return false;
547
548 regmatch_t match;
549 return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
550 }
551
552 // Initializes an RE from its string representation.
Init(const char * regex)553 void RE::Init(const char* regex) {
554 pattern_ = posix::StrDup(regex);
555
556 // Reserves enough bytes to hold the regular expression used for a
557 // full match.
558 const size_t full_regex_len = strlen(regex) + 10;
559 char* const full_pattern = new char[full_regex_len];
560
561 snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
562 is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
563 // We want to call regcomp(&partial_regex_, ...) even if the
564 // previous expression returns false. Otherwise partial_regex_ may
565 // not be properly initialized can may cause trouble when it's
566 // freed.
567 //
568 // Some implementation of POSIX regex (e.g. on at least some
569 // versions of Cygwin) doesn't accept the empty string as a valid
570 // regex. We change it to an equivalent form "()" to be safe.
571 if (is_valid_) {
572 const char* const partial_regex = (*regex == '\0') ? "()" : regex;
573 is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
574 }
575 EXPECT_TRUE(is_valid_)
576 << "Regular expression \"" << regex
577 << "\" is not a valid POSIX Extended regular expression.";
578
579 delete[] full_pattern;
580 }
581
582 #elif GTEST_USES_SIMPLE_RE
583
584 // Returns true iff ch appears anywhere in str (excluding the
585 // terminating '\0' character).
IsInSet(char ch,const char * str)586 bool IsInSet(char ch, const char* str) {
587 return ch != '\0' && strchr(str, ch) != NULL;
588 }
589
590 // Returns true iff ch belongs to the given classification. Unlike
591 // similar functions in <ctype.h>, these aren't affected by the
592 // current locale.
IsAsciiDigit(char ch)593 bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
IsAsciiPunct(char ch)594 bool IsAsciiPunct(char ch) {
595 return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
596 }
IsRepeat(char ch)597 bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
IsAsciiWhiteSpace(char ch)598 bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
IsAsciiWordChar(char ch)599 bool IsAsciiWordChar(char ch) {
600 return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
601 ('0' <= ch && ch <= '9') || ch == '_';
602 }
603
604 // Returns true iff "\\c" is a supported escape sequence.
IsValidEscape(char c)605 bool IsValidEscape(char c) {
606 return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
607 }
608
609 // Returns true iff the given atom (specified by escaped and pattern)
610 // matches ch. The result is undefined if the atom is invalid.
AtomMatchesChar(bool escaped,char pattern_char,char ch)611 bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
612 if (escaped) { // "\\p" where p is pattern_char.
613 switch (pattern_char) {
614 case 'd': return IsAsciiDigit(ch);
615 case 'D': return !IsAsciiDigit(ch);
616 case 'f': return ch == '\f';
617 case 'n': return ch == '\n';
618 case 'r': return ch == '\r';
619 case 's': return IsAsciiWhiteSpace(ch);
620 case 'S': return !IsAsciiWhiteSpace(ch);
621 case 't': return ch == '\t';
622 case 'v': return ch == '\v';
623 case 'w': return IsAsciiWordChar(ch);
624 case 'W': return !IsAsciiWordChar(ch);
625 }
626 return IsAsciiPunct(pattern_char) && pattern_char == ch;
627 }
628
629 return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
630 }
631
632 // Helper function used by ValidateRegex() to format error messages.
FormatRegexSyntaxError(const char * regex,int index)633 std::string FormatRegexSyntaxError(const char* regex, int index) {
634 return (Message() << "Syntax error at index " << index
635 << " in simple regular expression \"" << regex << "\": ").GetString();
636 }
637
638 // Generates non-fatal failures and returns false if regex is invalid;
639 // otherwise returns true.
ValidateRegex(const char * regex)640 bool ValidateRegex(const char* regex) {
641 if (regex == NULL) {
642 // TODO(wan@google.com): fix the source file location in the
643 // assertion failures to match where the regex is used in user
644 // code.
645 ADD_FAILURE() << "NULL is not a valid simple regular expression.";
646 return false;
647 }
648
649 bool is_valid = true;
650
651 // True iff ?, *, or + can follow the previous atom.
652 bool prev_repeatable = false;
653 for (int i = 0; regex[i]; i++) {
654 if (regex[i] == '\\') { // An escape sequence
655 i++;
656 if (regex[i] == '\0') {
657 ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
658 << "'\\' cannot appear at the end.";
659 return false;
660 }
661
662 if (!IsValidEscape(regex[i])) {
663 ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
664 << "invalid escape sequence \"\\" << regex[i] << "\".";
665 is_valid = false;
666 }
667 prev_repeatable = true;
668 } else { // Not an escape sequence.
669 const char ch = regex[i];
670
671 if (ch == '^' && i > 0) {
672 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
673 << "'^' can only appear at the beginning.";
674 is_valid = false;
675 } else if (ch == '$' && regex[i + 1] != '\0') {
676 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
677 << "'$' can only appear at the end.";
678 is_valid = false;
679 } else if (IsInSet(ch, "()[]{}|")) {
680 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
681 << "'" << ch << "' is unsupported.";
682 is_valid = false;
683 } else if (IsRepeat(ch) && !prev_repeatable) {
684 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
685 << "'" << ch << "' can only follow a repeatable token.";
686 is_valid = false;
687 }
688
689 prev_repeatable = !IsInSet(ch, "^$?*+");
690 }
691 }
692
693 return is_valid;
694 }
695
696 // Matches a repeated regex atom followed by a valid simple regular
697 // expression. The regex atom is defined as c if escaped is false,
698 // or \c otherwise. repeat is the repetition meta character (?, *,
699 // or +). The behavior is undefined if str contains too many
700 // characters to be indexable by size_t, in which case the test will
701 // probably time out anyway. We are fine with this limitation as
702 // std::string has it too.
MatchRepetitionAndRegexAtHead(bool escaped,char c,char repeat,const char * regex,const char * str)703 bool MatchRepetitionAndRegexAtHead(
704 bool escaped, char c, char repeat, const char* regex,
705 const char* str) {
706 const size_t min_count = (repeat == '+') ? 1 : 0;
707 const size_t max_count = (repeat == '?') ? 1 :
708 static_cast<size_t>(-1) - 1;
709 // We cannot call numeric_limits::max() as it conflicts with the
710 // max() macro on Windows.
711
712 for (size_t i = 0; i <= max_count; ++i) {
713 // We know that the atom matches each of the first i characters in str.
714 if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
715 // We have enough matches at the head, and the tail matches too.
716 // Since we only care about *whether* the pattern matches str
717 // (as opposed to *how* it matches), there is no need to find a
718 // greedy match.
719 return true;
720 }
721 if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
722 return false;
723 }
724 return false;
725 }
726
727 // Returns true iff regex matches a prefix of str. regex must be a
728 // valid simple regular expression and not start with "^", or the
729 // result is undefined.
MatchRegexAtHead(const char * regex,const char * str)730 bool MatchRegexAtHead(const char* regex, const char* str) {
731 if (*regex == '\0') // An empty regex matches a prefix of anything.
732 return true;
733
734 // "$" only matches the end of a string. Note that regex being
735 // valid guarantees that there's nothing after "$" in it.
736 if (*regex == '$')
737 return *str == '\0';
738
739 // Is the first thing in regex an escape sequence?
740 const bool escaped = *regex == '\\';
741 if (escaped)
742 ++regex;
743 if (IsRepeat(regex[1])) {
744 // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
745 // here's an indirect recursion. It terminates as the regex gets
746 // shorter in each recursion.
747 return MatchRepetitionAndRegexAtHead(
748 escaped, regex[0], regex[1], regex + 2, str);
749 } else {
750 // regex isn't empty, isn't "$", and doesn't start with a
751 // repetition. We match the first atom of regex with the first
752 // character of str and recurse.
753 return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
754 MatchRegexAtHead(regex + 1, str + 1);
755 }
756 }
757
758 // Returns true iff regex matches any substring of str. regex must be
759 // a valid simple regular expression, or the result is undefined.
760 //
761 // The algorithm is recursive, but the recursion depth doesn't exceed
762 // the regex length, so we won't need to worry about running out of
763 // stack space normally. In rare cases the time complexity can be
764 // exponential with respect to the regex length + the string length,
765 // but usually it's must faster (often close to linear).
MatchRegexAnywhere(const char * regex,const char * str)766 bool MatchRegexAnywhere(const char* regex, const char* str) {
767 if (regex == NULL || str == NULL)
768 return false;
769
770 if (*regex == '^')
771 return MatchRegexAtHead(regex + 1, str);
772
773 // A successful match can be anywhere in str.
774 do {
775 if (MatchRegexAtHead(regex, str))
776 return true;
777 } while (*str++ != '\0');
778 return false;
779 }
780
781 // Implements the RE class.
782
~RE()783 RE::~RE() {
784 free(const_cast<char*>(pattern_));
785 free(const_cast<char*>(full_pattern_));
786 }
787
788 // Returns true iff regular expression re matches the entire str.
FullMatch(const char * str,const RE & re)789 bool RE::FullMatch(const char* str, const RE& re) {
790 return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
791 }
792
793 // Returns true iff regular expression re matches a substring of str
794 // (including str itself).
PartialMatch(const char * str,const RE & re)795 bool RE::PartialMatch(const char* str, const RE& re) {
796 return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
797 }
798
799 // Initializes an RE from its string representation.
Init(const char * regex)800 void RE::Init(const char* regex) {
801 pattern_ = full_pattern_ = NULL;
802 if (regex != NULL) {
803 pattern_ = posix::StrDup(regex);
804 }
805
806 is_valid_ = ValidateRegex(regex);
807 if (!is_valid_) {
808 // No need to calculate the full pattern when the regex is invalid.
809 return;
810 }
811
812 const size_t len = strlen(regex);
813 // Reserves enough bytes to hold the regular expression used for a
814 // full match: we need space to prepend a '^', append a '$', and
815 // terminate the string with '\0'.
816 char* buffer = static_cast<char*>(malloc(len + 3));
817 full_pattern_ = buffer;
818
819 if (*regex != '^')
820 *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'.
821
822 // We don't use snprintf or strncpy, as they trigger a warning when
823 // compiled with VC++ 8.0.
824 memcpy(buffer, regex, len);
825 buffer += len;
826
827 if (len == 0 || regex[len - 1] != '$')
828 *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'.
829
830 *buffer = '\0';
831 }
832
833 #endif // GTEST_USES_POSIX_RE
834
835 const char kUnknownFile[] = "unknown file";
836
837 // Formats a source file path and a line number as they would appear
838 // in an error message from the compiler used to compile this code.
FormatFileLocation(const char * file,int line)839 GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
840 const std::string file_name(file == NULL ? kUnknownFile : file);
841
842 if (line < 0) {
843 return file_name + ":";
844 }
845 #ifdef _MSC_VER
846 return file_name + "(" + StreamableToString(line) + "):";
847 #else
848 return file_name + ":" + StreamableToString(line) + ":";
849 #endif // _MSC_VER
850 }
851
852 // Formats a file location for compiler-independent XML output.
853 // Although this function is not platform dependent, we put it next to
854 // FormatFileLocation in order to contrast the two functions.
855 // Note that FormatCompilerIndependentFileLocation() does NOT append colon
856 // to the file location it produces, unlike FormatFileLocation().
FormatCompilerIndependentFileLocation(const char * file,int line)857 GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
858 const char* file, int line) {
859 const std::string file_name(file == NULL ? kUnknownFile : file);
860
861 if (line < 0)
862 return file_name;
863 else
864 return file_name + ":" + StreamableToString(line);
865 }
866
867
GTestLog(GTestLogSeverity severity,const char * file,int line)868 GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
869 : severity_(severity) {
870 const char* const marker =
871 severity == GTEST_INFO ? "[ INFO ]" :
872 severity == GTEST_WARNING ? "[WARNING]" :
873 severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
874 GetStream() << ::std::endl << marker << " "
875 << FormatFileLocation(file, line).c_str() << ": ";
876 }
877
878 // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
~GTestLog()879 GTestLog::~GTestLog() {
880 GetStream() << ::std::endl;
881 if (severity_ == GTEST_FATAL) {
882 fflush(stderr);
883 posix::Abort();
884 }
885 }
886 // Disable Microsoft deprecation warnings for POSIX functions called from
887 // this class (creat, dup, dup2, and close)
888 #ifdef _MSC_VER
889 # pragma warning(push)
890 # pragma warning(disable: 4996)
891 #endif // _MSC_VER
892
893 #if GTEST_HAS_STREAM_REDIRECTION
894
895 // Object that captures an output stream (stdout/stderr).
896 class CapturedStream {
897 public:
898 // The ctor redirects the stream to a temporary file.
CapturedStream(int fd)899 explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
900 # if GTEST_OS_WINDOWS
901 char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
902 char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
903
904 ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
905 const UINT success = ::GetTempFileNameA(temp_dir_path,
906 "gtest_redir",
907 0, // Generate unique file name.
908 temp_file_path);
909 GTEST_CHECK_(success != 0)
910 << "Unable to create a temporary file in " << temp_dir_path;
911 const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
912 GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
913 << temp_file_path;
914 filename_ = temp_file_path;
915 # else
916 // There's no guarantee that a test has write access to the current
917 // directory, so we create the temporary file in the /tmp directory
918 // instead. We use /tmp on most systems, and /sdcard on Android.
919 // That's because Android doesn't have /tmp.
920 # if GTEST_OS_LINUX_ANDROID
921 // Note: Android applications are expected to call the framework's
922 // Context.getExternalStorageDirectory() method through JNI to get
923 // the location of the world-writable SD Card directory. However,
924 // this requires a Context handle, which cannot be retrieved
925 // globally from native code. Doing so also precludes running the
926 // code as part of a regular standalone executable, which doesn't
927 // run in a Dalvik process (e.g. when running it through 'adb shell').
928 //
929 // The location /sdcard is directly accessible from native code
930 // and is the only location (unofficially) supported by the Android
931 // team. It's generally a symlink to the real SD Card mount point
932 // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
933 // other OEM-customized locations. Never rely on these, and always
934 // use /sdcard.
935 char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
936 # else
937 char name_template[] = "/tmp/captured_stream.XXXXXX";
938 # endif // GTEST_OS_LINUX_ANDROID
939 const int captured_fd = mkstemp(name_template);
940 filename_ = name_template;
941 # endif // GTEST_OS_WINDOWS
942 fflush(NULL);
943 dup2(captured_fd, fd_);
944 close(captured_fd);
945 }
946
~CapturedStream()947 ~CapturedStream() {
948 remove(filename_.c_str());
949 }
950
GetCapturedString()951 std::string GetCapturedString() {
952 if (uncaptured_fd_ != -1) {
953 // Restores the original stream.
954 fflush(NULL);
955 dup2(uncaptured_fd_, fd_);
956 close(uncaptured_fd_);
957 uncaptured_fd_ = -1;
958 }
959
960 FILE* const file = posix::FOpen(filename_.c_str(), "r");
961 const std::string content = ReadEntireFile(file);
962 posix::FClose(file);
963 return content;
964 }
965
966 private:
967 // Reads the entire content of a file as an std::string.
968 static std::string ReadEntireFile(FILE* file);
969
970 // Returns the size (in bytes) of a file.
971 static size_t GetFileSize(FILE* file);
972
973 const int fd_; // A stream to capture.
974 int uncaptured_fd_;
975 // Name of the temporary file holding the stderr output.
976 ::std::string filename_;
977
978 GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
979 };
980
981 // Returns the size (in bytes) of a file.
GetFileSize(FILE * file)982 size_t CapturedStream::GetFileSize(FILE* file) {
983 fseek(file, 0, SEEK_END);
984 return static_cast<size_t>(ftell(file));
985 }
986
987 // Reads the entire content of a file as a string.
ReadEntireFile(FILE * file)988 std::string CapturedStream::ReadEntireFile(FILE* file) {
989 const size_t file_size = GetFileSize(file);
990 char* const buffer = new char[file_size];
991
992 size_t bytes_last_read = 0; // # of bytes read in the last fread()
993 size_t bytes_read = 0; // # of bytes read so far
994
995 fseek(file, 0, SEEK_SET);
996
997 // Keeps reading the file until we cannot read further or the
998 // pre-determined file size is reached.
999 do {
1000 bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
1001 bytes_read += bytes_last_read;
1002 } while (bytes_last_read > 0 && bytes_read < file_size);
1003
1004 const std::string content(buffer, bytes_read);
1005 delete[] buffer;
1006
1007 return content;
1008 }
1009
1010 # ifdef _MSC_VER
1011 # pragma warning(pop)
1012 # endif // _MSC_VER
1013
1014 static CapturedStream* g_captured_stderr = NULL;
1015 static CapturedStream* g_captured_stdout = NULL;
1016
1017 // Starts capturing an output stream (stdout/stderr).
CaptureStream(int fd,const char * stream_name,CapturedStream ** stream)1018 void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
1019 if (*stream != NULL) {
1020 GTEST_LOG_(FATAL) << "Only one " << stream_name
1021 << " capturer can exist at a time.";
1022 }
1023 *stream = new CapturedStream(fd);
1024 }
1025
1026 // Stops capturing the output stream and returns the captured string.
GetCapturedStream(CapturedStream ** captured_stream)1027 std::string GetCapturedStream(CapturedStream** captured_stream) {
1028 const std::string content = (*captured_stream)->GetCapturedString();
1029
1030 delete *captured_stream;
1031 *captured_stream = NULL;
1032
1033 return content;
1034 }
1035
1036 // Starts capturing stdout.
CaptureStdout()1037 void CaptureStdout() {
1038 CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
1039 }
1040
1041 // Starts capturing stderr.
CaptureStderr()1042 void CaptureStderr() {
1043 CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
1044 }
1045
1046 // Stops capturing stdout and returns the captured string.
GetCapturedStdout()1047 std::string GetCapturedStdout() {
1048 return GetCapturedStream(&g_captured_stdout);
1049 }
1050
1051 // Stops capturing stderr and returns the captured string.
GetCapturedStderr()1052 std::string GetCapturedStderr() {
1053 return GetCapturedStream(&g_captured_stderr);
1054 }
1055
1056 #endif // GTEST_HAS_STREAM_REDIRECTION
1057
1058 #if GTEST_HAS_DEATH_TEST
1059
1060 // A copy of all command line arguments. Set by InitGoogleTest().
1061 ::std::vector<testing::internal::string> g_argvs;
1062
1063 static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
1064 NULL; // Owned.
1065
SetInjectableArgvs(const::std::vector<testing::internal::string> * argvs)1066 void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
1067 if (g_injected_test_argvs != argvs)
1068 delete g_injected_test_argvs;
1069 g_injected_test_argvs = argvs;
1070 }
1071
GetInjectableArgvs()1072 const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
1073 if (g_injected_test_argvs != NULL) {
1074 return *g_injected_test_argvs;
1075 }
1076 return g_argvs;
1077 }
1078 #endif // GTEST_HAS_DEATH_TEST
1079
1080 #if GTEST_OS_WINDOWS_MOBILE
1081 namespace posix {
Abort()1082 void Abort() {
1083 DebugBreak();
1084 TerminateProcess(GetCurrentProcess(), 1);
1085 }
1086 } // namespace posix
1087 #endif // GTEST_OS_WINDOWS_MOBILE
1088
1089 // Returns the name of the environment variable corresponding to the
1090 // given flag. For example, FlagToEnvVar("foo") will return
1091 // "GTEST_FOO" in the open-source version.
FlagToEnvVar(const char * flag)1092 static std::string FlagToEnvVar(const char* flag) {
1093 const std::string full_flag =
1094 (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
1095
1096 Message env_var;
1097 for (size_t i = 0; i != full_flag.length(); i++) {
1098 env_var << ToUpper(full_flag.c_str()[i]);
1099 }
1100
1101 return env_var.GetString();
1102 }
1103
1104 // Parses 'str' for a 32-bit signed integer. If successful, writes
1105 // the result to *value and returns true; otherwise leaves *value
1106 // unchanged and returns false.
ParseInt32(const Message & src_text,const char * str,Int32 * value)1107 bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
1108 // Parses the environment variable as a decimal integer.
1109 char* end = NULL;
1110 const long long_value = strtol(str, &end, 10); // NOLINT
1111
1112 // Has strtol() consumed all characters in the string?
1113 if (*end != '\0') {
1114 // No - an invalid character was encountered.
1115 Message msg;
1116 msg << "WARNING: " << src_text
1117 << " is expected to be a 32-bit integer, but actually"
1118 << " has value \"" << str << "\".\n";
1119 printf("%s", msg.GetString().c_str());
1120 fflush(stdout);
1121 return false;
1122 }
1123
1124 // Is the parsed value in the range of an Int32?
1125 const Int32 result = static_cast<Int32>(long_value);
1126 if (long_value == LONG_MAX || long_value == LONG_MIN ||
1127 // The parsed value overflows as a long. (strtol() returns
1128 // LONG_MAX or LONG_MIN when the input overflows.)
1129 result != long_value
1130 // The parsed value overflows as an Int32.
1131 ) {
1132 Message msg;
1133 msg << "WARNING: " << src_text
1134 << " is expected to be a 32-bit integer, but actually"
1135 << " has value " << str << ", which overflows.\n";
1136 printf("%s", msg.GetString().c_str());
1137 fflush(stdout);
1138 return false;
1139 }
1140
1141 *value = result;
1142 return true;
1143 }
1144
1145 // Reads and returns the Boolean environment variable corresponding to
1146 // the given flag; if it's not set, returns default_value.
1147 //
1148 // The value is considered true iff it's not "0".
BoolFromGTestEnv(const char * flag,bool default_value)1149 bool BoolFromGTestEnv(const char* flag, bool default_value) {
1150 const std::string env_var = FlagToEnvVar(flag);
1151 const char* const string_value = posix::GetEnv(env_var.c_str());
1152 return string_value == NULL ?
1153 default_value : strcmp(string_value, "0") != 0;
1154 }
1155
1156 // Reads and returns a 32-bit integer stored in the environment
1157 // variable corresponding to the given flag; if it isn't set or
1158 // doesn't represent a valid 32-bit integer, returns default_value.
Int32FromGTestEnv(const char * flag,Int32 default_value)1159 Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
1160 const std::string env_var = FlagToEnvVar(flag);
1161 const char* const string_value = posix::GetEnv(env_var.c_str());
1162 if (string_value == NULL) {
1163 // The environment variable is not set.
1164 return default_value;
1165 }
1166
1167 Int32 result = default_value;
1168 if (!ParseInt32(Message() << "Environment variable " << env_var,
1169 string_value, &result)) {
1170 printf("The default value %s is used.\n",
1171 (Message() << default_value).GetString().c_str());
1172 fflush(stdout);
1173 return default_value;
1174 }
1175
1176 return result;
1177 }
1178
1179 // Reads and returns the string environment variable corresponding to
1180 // the given flag; if it's not set, returns default_value.
StringFromGTestEnv(const char * flag,const char * default_value)1181 const char* StringFromGTestEnv(const char* flag, const char* default_value) {
1182 const std::string env_var = FlagToEnvVar(flag);
1183 const char* const value = posix::GetEnv(env_var.c_str());
1184 return value == NULL ? default_value : value;
1185 }
1186
1187 } // namespace internal
1188 } // namespace testing
1189