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