/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 |