11be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Copyright 2008, Google Inc. 21be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// All rights reserved. 31be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 41be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Redistribution and use in source and binary forms, with or without 51be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// modification, are permitted provided that the following conditions are 61be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// met: 71be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 81be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// * Redistributions of source code must retain the above copyright 91be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// notice, this list of conditions and the following disclaimer. 101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// * Redistributions in binary form must reproduce the above 111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// copyright notice, this list of conditions and the following disclaimer 121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// in the documentation and/or other materials provided with the 131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// distribution. 141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// * Neither the name of Google Inc. nor the names of its 151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// contributors may be used to endorse or promote products derived from 161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// this software without specific prior written permission. 171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Author: wan@google.com (Zhanyong Wan) 311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-port.h" 331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3442028ec214cdb680c4987f7183ed384b5b9d4ce3Marcus Oakland#include <errno.h> 351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <limits.h> 361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <stdlib.h> 371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <stdio.h> 3841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include <string.h> 391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_WINDOWS_MOBILE 4141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <windows.h> // For TerminateProcess() 4241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif GTEST_OS_WINDOWS 4341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <io.h> 4441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <sys/stat.h> 451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#else 4641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <unistd.h> 4741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_WINDOWS_MOBILE 481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_MAC 5041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/mach_init.h> 5141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/task.h> 5241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/vm_map.h> 5341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_MAC 541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 55fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes#if GTEST_OS_QNX 56fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes# include <devctl.h> 57fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes# include <sys/procfs.h> 58fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes#endif // GTEST_OS_QNX 59fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes 6041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/gtest-spi.h" 6141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/gtest-message.h" 6241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-internal.h" 6341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-string.h" 641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Indicates that this translation unit is part of Google Test's 661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// implementation. It must come before gtest-internal-inl.h is 671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// included, or there will be a compiler error. This trick is to 681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// prevent a user from accidentally including gtest-internal-inl.h in 691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// his code. 701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#define GTEST_IMPLEMENTATION_ 1 711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include "src/gtest-internal-inl.h" 721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#undef GTEST_IMPLEMENTATION_ 731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catanianamespace testing { 751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catanianamespace internal { 761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if defined(_MSC_VER) || defined(__BORLANDC__) 7841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// MSVC and C++Builder do not provide a definition of STDERR_FILENO. 7941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst int kStdOutFileno = 1; 801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst int kStdErrFileno = 2; 811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#else 8241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst int kStdOutFileno = STDOUT_FILENO; 831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst int kStdErrFileno = STDERR_FILENO; 8441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // _MSC_VER 8541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 8641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_MAC 8741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 8841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Returns the number of threads running in the process, or 0 to indicate that 8941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// we cannot detect it. 9041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t GetThreadCount() { 9141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const task_t task = mach_task_self(); 9241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot mach_msg_type_number_t thread_count; 9341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot thread_act_array_t thread_list; 9441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const kern_return_t status = task_threads(task, &thread_list, &thread_count); 9541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (status == KERN_SUCCESS) { 9641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // task_threads allocates resources in thread_list and we need to free them 9741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // to avoid leaks. 9841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot vm_deallocate(task, 9941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot reinterpret_cast<vm_address_t>(thread_list), 10041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot sizeof(thread_t) * thread_count); 10141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return static_cast<size_t>(thread_count); 10241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } else { 10341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return 0; 10441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 10541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 10641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 107fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes#elif GTEST_OS_QNX 108fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes 109fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes// Returns the number of threads running in the process, or 0 to indicate that 110fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes// we cannot detect it. 111fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughessize_t GetThreadCount() { 112fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const int fd = open("/proc/self/as", O_RDONLY); 113fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes if (fd < 0) { 114fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return 0; 115fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes } 116fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes procfs_info process_info; 117fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const int status = 118fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); 119fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes close(fd); 120fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes if (status == EOK) { 121fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return static_cast<size_t>(process_info.num_threads); 122fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes } else { 123fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return 0; 124fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes } 125fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes} 126fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes 12741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#else 12841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 12941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t GetThreadCount() { 13041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // There's no portable way to detect the number of threads, so we just 13141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // return 0 to indicate that we cannot detect it. 13241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return 0; 13341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 13441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 13541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_MAC 1361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#if GTEST_USES_POSIX_RE 1381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Implements RE. Currently only needed for death tests. 1401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1411be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaRE::~RE() { 14241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (is_valid_) { 14341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // regfree'ing an invalid regex might crash because the content 14441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // of the regex is undefined. Since the regex's are essentially 14541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // the same, one cannot be valid (or invalid) without the other 14641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // being so too. 14741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot regfree(&partial_regex_); 14841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot regfree(&full_regex_); 14941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 1501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania free(const_cast<char*>(pattern_)); 1511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches the entire str. 1541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::FullMatch(const char* str, const RE& re) { 1551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!re.is_valid_) return false; 1561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania regmatch_t match; 1581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return regexec(&re.full_regex_, str, 1, &match, 0) == 0; 1591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches a substring of str 1621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (including str itself). 1631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::PartialMatch(const char* str, const RE& re) { 1641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!re.is_valid_) return false; 1651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania regmatch_t match; 1671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; 1681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Initializes an RE from its string representation. 1711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniavoid RE::Init(const char* regex) { 17241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot pattern_ = posix::StrDup(regex); 1731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Reserves enough bytes to hold the regular expression used for a 1751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // full match. 1761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t full_regex_len = strlen(regex) + 10; 1771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* const full_pattern = new char[full_regex_len]; 1781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania snprintf(full_pattern, full_regex_len, "^(%s)$", regex); 1801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; 1811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We want to call regcomp(&partial_regex_, ...) even if the 1821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // previous expression returns false. Otherwise partial_regex_ may 1831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // not be properly initialized can may cause trouble when it's 1841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // freed. 1851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // 1861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Some implementation of POSIX regex (e.g. on at least some 1871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // versions of Cygwin) doesn't accept the empty string as a valid 1881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // regex. We change it to an equivalent form "()" to be safe. 18941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (is_valid_) { 19041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const partial_regex = (*regex == '\0') ? "()" : regex; 19141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; 19241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 1931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania EXPECT_TRUE(is_valid_) 1941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "Regular expression \"" << regex 1951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "\" is not a valid POSIX Extended regular expression."; 1961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania delete[] full_pattern; 1981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#elif GTEST_USES_SIMPLE_RE 2011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff ch appears anywhere in str (excluding the 2031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// terminating '\0' character). 2041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsInSet(char ch, const char* str) { 2051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return ch != '\0' && strchr(str, ch) != NULL; 2061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff ch belongs to the given classification. Unlike 2091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// similar functions in <ctype.h>, these aren't affected by the 2101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// current locale. 21141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } 21241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiPunct(char ch) { 2131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); 2141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } 21641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } 21741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiWordChar(char ch) { 2181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || 2191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ('0' <= ch && ch <= '9') || ch == '_'; 2201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff "\\c" is a supported escape sequence. 2231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsValidEscape(char c) { 22441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); 2251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff the given atom (specified by escaped and pattern) 2281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// matches ch. The result is undefined if the atom is invalid. 2291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool AtomMatchesChar(bool escaped, char pattern_char, char ch) { 2301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (escaped) { // "\\p" where p is pattern_char. 2311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania switch (pattern_char) { 23241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'd': return IsAsciiDigit(ch); 23341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'D': return !IsAsciiDigit(ch); 2341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'f': return ch == '\f'; 2351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'n': return ch == '\n'; 2361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'r': return ch == '\r'; 23741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 's': return IsAsciiWhiteSpace(ch); 23841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'S': return !IsAsciiWhiteSpace(ch); 2391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 't': return ch == '\t'; 2401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'v': return ch == '\v'; 24141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'w': return IsAsciiWordChar(ch); 24241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'W': return !IsAsciiWordChar(ch); 2431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 24441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return IsAsciiPunct(pattern_char) && pattern_char == ch; 2451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return (pattern_char == '.' && ch != '\n') || pattern_char == ch; 2481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Helper function used by ValidateRegex() to format error messages. 251fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesstd::string FormatRegexSyntaxError(const char* regex, int index) { 2521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return (Message() << "Syntax error at index " << index 2531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " in simple regular expression \"" << regex << "\": ").GetString(); 2541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Generates non-fatal failures and returns false if regex is invalid; 2571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// otherwise returns true. 2581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool ValidateRegex(const char* regex) { 2591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex == NULL) { 2601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // TODO(wan@google.com): fix the source file location in the 2611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // assertion failures to match where the regex is used in user 2621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // code. 2631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << "NULL is not a valid simple regular expression."; 2641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 2651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bool is_valid = true; 2681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // True iff ?, *, or + can follow the previous atom. 2701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bool prev_repeatable = false; 2711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania for (int i = 0; regex[i]; i++) { 2721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex[i] == '\\') { // An escape sequence 2731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania i++; 2741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex[i] == '\0') { 2751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) 2761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'\\' cannot appear at the end."; 2771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 2781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!IsValidEscape(regex[i])) { 2811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) 2821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "invalid escape sequence \"\\" << regex[i] << "\"."; 2831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania prev_repeatable = true; 2861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else { // Not an escape sequence. 2871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const char ch = regex[i]; 2881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (ch == '^' && i > 0) { 2901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 2911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'^' can only appear at the beginning."; 2921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else if (ch == '$' && regex[i + 1] != '\0') { 2941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 2951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'$' can only appear at the end."; 2961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else if (IsInSet(ch, "()[]{}|")) { 2981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 2991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'" << ch << "' is unsupported."; 3001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 3011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else if (IsRepeat(ch) && !prev_repeatable) { 3021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 3031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'" << ch << "' can only follow a repeatable token."; 3041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 3051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania prev_repeatable = !IsInSet(ch, "^$?*+"); 3081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return is_valid; 3121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Matches a repeated regex atom followed by a valid simple regular 3151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// expression. The regex atom is defined as c if escaped is false, 3161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// or \c otherwise. repeat is the repetition meta character (?, *, 3171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// or +). The behavior is undefined if str contains too many 3181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// characters to be indexable by size_t, in which case the test will 3191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// probably time out anyway. We are fine with this limitation as 3201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// std::string has it too. 3211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRepetitionAndRegexAtHead( 3221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bool escaped, char c, char repeat, const char* regex, 3231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const char* str) { 3241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t min_count = (repeat == '+') ? 1 : 0; 3251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t max_count = (repeat == '?') ? 1 : 3261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania static_cast<size_t>(-1) - 1; 3271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We cannot call numeric_limits::max() as it conflicts with the 3281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // max() macro on Windows. 3291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania for (size_t i = 0; i <= max_count; ++i) { 3311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We know that the atom matches each of the first i characters in str. 3321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (i >= min_count && MatchRegexAtHead(regex, str + i)) { 3331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We have enough matches at the head, and the tail matches too. 3341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Since we only care about *whether* the pattern matches str 3351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // (as opposed to *how* it matches), there is no need to find a 3361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // greedy match. 3371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 3381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) 3401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regex matches a prefix of str. regex must be a 3461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// valid simple regular expression and not start with "^", or the 3471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// result is undefined. 3481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRegexAtHead(const char* regex, const char* str) { 3491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex == '\0') // An empty regex matches a prefix of anything. 3501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 3511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // "$" only matches the end of a string. Note that regex being 3531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // valid guarantees that there's nothing after "$" in it. 3541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex == '$') 3551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return *str == '\0'; 3561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Is the first thing in regex an escape sequence? 3581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const bool escaped = *regex == '\\'; 3591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (escaped) 3601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ++regex; 3611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (IsRepeat(regex[1])) { 3621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so 3631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // here's an indirect recursion. It terminates as the regex gets 3641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // shorter in each recursion. 3651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return MatchRepetitionAndRegexAtHead( 3661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania escaped, regex[0], regex[1], regex + 2, str); 3671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else { 3681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // regex isn't empty, isn't "$", and doesn't start with a 3691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // repetition. We match the first atom of regex with the first 3701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // character of str and recurse. 3711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && 3721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania MatchRegexAtHead(regex + 1, str + 1); 3731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regex matches any substring of str. regex must be 3771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// a valid simple regular expression, or the result is undefined. 3781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 3791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// The algorithm is recursive, but the recursion depth doesn't exceed 3801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the regex length, so we won't need to worry about running out of 3811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// stack space normally. In rare cases the time complexity can be 3821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// exponential with respect to the regex length + the string length, 3831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// but usually it's must faster (often close to linear). 3841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRegexAnywhere(const char* regex, const char* str) { 3851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex == NULL || str == NULL) 3861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex == '^') 3891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return MatchRegexAtHead(regex + 1, str); 3901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // A successful match can be anywhere in str. 3921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania do { 3931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (MatchRegexAtHead(regex, str)) 3941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 3951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } while (*str++ != '\0'); 3961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Implements the RE class. 4001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4011be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaRE::~RE() { 4021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania free(const_cast<char*>(pattern_)); 4031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania free(const_cast<char*>(full_pattern_)); 4041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 4051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches the entire str. 4071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::FullMatch(const char* str, const RE& re) { 4081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); 4091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 4101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches a substring of str 4121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (including str itself). 4131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::PartialMatch(const char* str, const RE& re) { 4141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); 4151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 4161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Initializes an RE from its string representation. 4181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniavoid RE::Init(const char* regex) { 4191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania pattern_ = full_pattern_ = NULL; 4201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex != NULL) { 42141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot pattern_ = posix::StrDup(regex); 4221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 4231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid_ = ValidateRegex(regex); 4251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!is_valid_) { 4261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // No need to calculate the full pattern when the regex is invalid. 4271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return; 4281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 4291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t len = strlen(regex); 4311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Reserves enough bytes to hold the regular expression used for a 4321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // full match: we need space to prepend a '^', append a '$', and 4331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // terminate the string with '\0'. 4341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* buffer = static_cast<char*>(malloc(len + 3)); 4351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania full_pattern_ = buffer; 4361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex != '^') 4381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. 4391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We don't use snprintf or strncpy, as they trigger a warning when 4411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // compiled with VC++ 8.0. 4421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania memcpy(buffer, regex, len); 4431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania buffer += len; 4441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (len == 0 || regex[len - 1] != '$') 4461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. 4471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *buffer = '\0'; 4491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 4501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif // GTEST_USES_POSIX_RE 4521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 45341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst char kUnknownFile[] = "unknown file"; 45441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 45541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Formats a source file path and a line number as they would appear 45641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// in an error message from the compiler used to compile this code. 45741d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { 458fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string file_name(file == NULL ? kUnknownFile : file); 45941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 46041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (line < 0) { 461fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return file_name + ":"; 46241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 46341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#ifdef _MSC_VER 464fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return file_name + "(" + StreamableToString(line) + "):"; 46541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#else 466fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return file_name + ":" + StreamableToString(line) + ":"; 46741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // _MSC_VER 46841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 46941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 47041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Formats a file location for compiler-independent XML output. 47141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Although this function is not platform dependent, we put it next to 47241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// FormatFileLocation in order to contrast the two functions. 47341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Note that FormatCompilerIndependentFileLocation() does NOT append colon 47441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// to the file location it produces, unlike FormatFileLocation(). 47541d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTEST_API_ ::std::string FormatCompilerIndependentFileLocation( 47641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* file, int line) { 477fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string file_name(file == NULL ? kUnknownFile : file); 47841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 47941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (line < 0) 48041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return file_name; 48141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot else 482fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return file_name + ":" + StreamableToString(line); 48341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 48441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 48541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 48641d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) 48741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot : severity_(severity) { 4881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const char* const marker = 4891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania severity == GTEST_INFO ? "[ INFO ]" : 4901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania severity == GTEST_WARNING ? "[WARNING]" : 4911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; 49241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GetStream() << ::std::endl << marker << " " 49341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << FormatFileLocation(file, line).c_str() << ": "; 4941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 4951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 49641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. 49741d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTestLog::~GTestLog() { 49841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GetStream() << ::std::endl; 49941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (severity_ == GTEST_FATAL) { 50041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot fflush(stderr); 50141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot posix::Abort(); 50241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 50341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 5041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Disable Microsoft deprecation warnings for POSIX functions called from 5051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// this class (creat, dup, dup2, and close) 5061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#ifdef _MSC_VER 50741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(push) 50841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(disable: 4996) 5091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif // _MSC_VER 5101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 51141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_HAS_STREAM_REDIRECTION 5121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 51341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Object that captures an output stream (stdout/stderr). 51441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotclass CapturedStream { 5151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania public: 51641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // The ctor redirects the stream to a temporary file. 517fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { 51841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# if GTEST_OS_WINDOWS 5191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT 5201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT 5211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); 52341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const UINT success = ::GetTempFileNameA(temp_dir_path, 52441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot "gtest_redir", 52541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 0, // Generate unique file name. 52641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot temp_file_path); 52741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_CHECK_(success != 0) 52841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << "Unable to create a temporary file in " << temp_dir_path; 5291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); 53041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " 53141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << temp_file_path; 5321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania filename_ = temp_file_path; 533fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes// BEGIN android-changed 53441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif GTEST_OS_LINUX_ANDROID 5355ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris // Attempt to create the temporary file in this directory: 5365ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris // $ANDROID_DATA/local/tmp 5375ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris ::std::string str_template; 5385ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris const char* android_data = getenv("ANDROID_DATA"); 5395ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris if (android_data == NULL) { 54042028ec214cdb680c4987f7183ed384b5b9d4ce3Marcus Oakland // If $ANDROID_DATA is not set, then fall back to /tmp. 5415ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris str_template = "/tmp"; 5425ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris } else { 5435ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris str_template = ::std::string(android_data) + "/local/tmp"; 544344e5f3db17615cc853073a02968a603efd39109Stephen Hines } 5455ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris str_template += "/captured_stderr.XXXXXX"; 5465ad2a0ee80be8d3d14a5fb3ef838b7ae7efb65f1Christopher Ferris char* name_template = strdup(str_template.c_str()); 54784190c7c1f1b899ad83fdd8e110bde08ad281534Nicolas Catania const int captured_fd = mkstemp(name_template); 548d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " 54942028ec214cdb680c4987f7183ed384b5b9d4ce3Marcus Oakland << name_template << ": " 55042028ec214cdb680c4987f7183ed384b5b9d4ce3Marcus Oakland << strerror(errno); 55184190c7c1f1b899ad83fdd8e110bde08ad281534Nicolas Catania filename_ = name_template; 552344e5f3db17615cc853073a02968a603efd39109Stephen Hines free(name_template); 553344e5f3db17615cc853073a02968a603efd39109Stephen Hines name_template = NULL; 55441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# else 555fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes // There's no guarantee that a test has write access to the current 556fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes // directory, so we create the temporary file in the /tmp directory 5573fc9a00f8e249a224093997f8059ad6cfc76a3d6Elliott Hughes // instead. 55841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot char name_template[] = "/tmp/captured_stream.XXXXXX"; 5593fc9a00f8e249a224093997f8059ad6cfc76a3d6Elliott Hughes// END android-changed 5601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const int captured_fd = mkstemp(name_template); 5611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania filename_ = name_template; 56241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# endif // GTEST_OS_WINDOWS 5631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(NULL); 56441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot dup2(captured_fd, fd_); 5651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania close(captured_fd); 5661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 5671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 56841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot ~CapturedStream() { 5691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania remove(filename_.c_str()); 5701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 5711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 572fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes std::string GetCapturedString() { 57341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (uncaptured_fd_ != -1) { 57441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // Restores the original stream. 57541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot fflush(NULL); 57641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot dup2(uncaptured_fd_, fd_); 57741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot close(uncaptured_fd_); 57841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot uncaptured_fd_ = -1; 57941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 5801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 58141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot FILE* const file = posix::FOpen(filename_.c_str(), "r"); 582fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes// BEGIN android-changed 58342028ec214cdb680c4987f7183ed384b5b9d4ce3Marcus Oakland GTEST_CHECK_(file != NULL) << "Unable to open temporary file " 58442028ec214cdb680c4987f7183ed384b5b9d4ce3Marcus Oakland << filename_.c_str() << ": " 58542028ec214cdb680c4987f7183ed384b5b9d4ce3Marcus Oakland << strerror(errno); 586fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes// END android-changed 587fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string content = ReadEntireFile(file); 58841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot posix::FClose(file); 58941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return content; 59041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 5911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania private: 593fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes // Reads the entire content of a file as an std::string. 594fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes static std::string ReadEntireFile(FILE* file); 59541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 59641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // Returns the size (in bytes) of a file. 59741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot static size_t GetFileSize(FILE* file); 59841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 59941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const int fd_; // A stream to capture. 6001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania int uncaptured_fd_; 60141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // Name of the temporary file holding the stderr output. 6021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ::std::string filename_; 6031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 60441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); 60541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}; 6061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the size (in bytes) of a file. 60841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t CapturedStream::GetFileSize(FILE* file) { 6091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fseek(file, 0, SEEK_END); 6101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return static_cast<size_t>(ftell(file)); 6111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads the entire content of a file as a string. 614fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesstd::string CapturedStream::ReadEntireFile(FILE* file) { 6151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t file_size = GetFileSize(file); 6161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* const buffer = new char[file_size]; 6171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania size_t bytes_last_read = 0; // # of bytes read in the last fread() 6191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania size_t bytes_read = 0; // # of bytes read so far 6201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fseek(file, 0, SEEK_SET); 6221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Keeps reading the file until we cannot read further or the 6241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // pre-determined file size is reached. 6251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania do { 6261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); 6271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bytes_read += bytes_last_read; 6281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } while (bytes_last_read > 0 && bytes_read < file_size); 6291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 630fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string content(buffer, bytes_read); 6311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania delete[] buffer; 6321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return content; 6341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 63641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# ifdef _MSC_VER 63741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(pop) 63841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# endif // _MSC_VER 63941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 64041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CapturedStream* g_captured_stderr = NULL; 64141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CapturedStream* g_captured_stdout = NULL; 64241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 64341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing an output stream (stdout/stderr). 64441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { 64541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (*stream != NULL) { 64641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_LOG_(FATAL) << "Only one " << stream_name 64741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << " capturer can exist at a time."; 6481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 64941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot *stream = new CapturedStream(fd); 6501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 65241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing the output stream and returns the captured string. 653fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesstd::string GetCapturedStream(CapturedStream** captured_stream) { 654fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string content = (*captured_stream)->GetCapturedString(); 6551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 65641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot delete *captured_stream; 65741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot *captured_stream = NULL; 6581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return content; 6601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 66241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing stdout. 66341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStdout() { 66441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); 66541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 66641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 66741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing stderr. 66841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStderr() { 66941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); 67041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 67141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 67241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing stdout and returns the captured string. 673fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesstd::string GetCapturedStdout() { 674fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return GetCapturedStream(&g_captured_stdout); 675fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes} 67641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 67741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing stderr and returns the captured string. 678fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesstd::string GetCapturedStderr() { 679fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return GetCapturedStream(&g_captured_stderr); 680fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes} 68141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 68241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_HAS_STREAM_REDIRECTION 6831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#if GTEST_HAS_DEATH_TEST 6851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// A copy of all command line arguments. Set by InitGoogleTest(). 687fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes::std::vector<testing::internal::string> g_argvs; 6881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 689fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesstatic const ::std::vector<testing::internal::string>* g_injected_test_argvs = 690fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes NULL; // Owned. 6911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 692fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesvoid SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) { 693fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes if (g_injected_test_argvs != argvs) 694fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes delete g_injected_test_argvs; 695fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes g_injected_test_argvs = argvs; 696fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes} 697fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes 698fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesconst ::std::vector<testing::internal::string>& GetInjectableArgvs() { 699fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes if (g_injected_test_argvs != NULL) { 700fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return *g_injected_test_argvs; 701fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes } 702fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes return g_argvs; 703fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes} 7041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif // GTEST_HAS_DEATH_TEST 7051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 70641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_WINDOWS_MOBILE 70741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotnamespace posix { 70841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid Abort() { 7091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania DebugBreak(); 7101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania TerminateProcess(GetCurrentProcess(), 1); 7111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 71241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} // namespace posix 71341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_WINDOWS_MOBILE 7141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the name of the environment variable corresponding to the 7161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// given flag. For example, FlagToEnvVar("foo") will return 7171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// "GTEST_FOO" in the open-source version. 718fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughesstatic std::string FlagToEnvVar(const char* flag) { 719fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string full_flag = 7201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); 7211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Message env_var; 72341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot for (size_t i = 0; i != full_flag.length(); i++) { 72441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot env_var << ToUpper(full_flag.c_str()[i]); 7251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return env_var.GetString(); 7281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 7291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Parses 'str' for a 32-bit signed integer. If successful, writes 7311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the result to *value and returns true; otherwise leaves *value 7321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// unchanged and returns false. 7331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool ParseInt32(const Message& src_text, const char* str, Int32* value) { 7341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Parses the environment variable as a decimal integer. 7351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* end = NULL; 7361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const long long_value = strtol(str, &end, 10); // NOLINT 7371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Has strtol() consumed all characters in the string? 7391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*end != '\0') { 7401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // No - an invalid character was encountered. 7411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Message msg; 7421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania msg << "WARNING: " << src_text 7431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " is expected to be a 32-bit integer, but actually" 7441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " has value \"" << str << "\".\n"; 7451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania printf("%s", msg.GetString().c_str()); 7461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(stdout); 7471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 7481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Is the parsed value in the range of an Int32? 7511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const Int32 result = static_cast<Int32>(long_value); 7521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (long_value == LONG_MAX || long_value == LONG_MIN || 7531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // The parsed value overflows as a long. (strtol() returns 7541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // LONG_MAX or LONG_MIN when the input overflows.) 7551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania result != long_value 7561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // The parsed value overflows as an Int32. 7571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ) { 7581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Message msg; 7591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania msg << "WARNING: " << src_text 7601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " is expected to be a 32-bit integer, but actually" 7611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " has value " << str << ", which overflows.\n"; 7621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania printf("%s", msg.GetString().c_str()); 7631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(stdout); 7641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 7651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *value = result; 7681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 7691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 7701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns the Boolean environment variable corresponding to 7721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the given flag; if it's not set, returns default_value. 7731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 7741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// The value is considered true iff it's not "0". 7751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool BoolFromGTestEnv(const char* flag, bool default_value) { 776fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string env_var = FlagToEnvVar(flag); 77741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const string_value = posix::GetEnv(env_var.c_str()); 7781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return string_value == NULL ? 7791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania default_value : strcmp(string_value, "0") != 0; 7801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 7811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns a 32-bit integer stored in the environment 7831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// variable corresponding to the given flag; if it isn't set or 7841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// doesn't represent a valid 32-bit integer, returns default_value. 7851be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaInt32 Int32FromGTestEnv(const char* flag, Int32 default_value) { 786fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string env_var = FlagToEnvVar(flag); 78741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const string_value = posix::GetEnv(env_var.c_str()); 7881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (string_value == NULL) { 7891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // The environment variable is not set. 7901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return default_value; 7911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Int32 result = default_value; 7941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!ParseInt32(Message() << "Environment variable " << env_var, 7951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania string_value, &result)) { 7961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania printf("The default value %s is used.\n", 7971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania (Message() << default_value).GetString().c_str()); 7981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(stdout); 7991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return default_value; 8001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 8011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 8021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return result; 8031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 8041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 8051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns the string environment variable corresponding to 8061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the given flag; if it's not set, returns default_value. 8071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst char* StringFromGTestEnv(const char* flag, const char* default_value) { 808fc2de66453b0669c09eaca643b07d34443858b6fElliott Hughes const std::string env_var = FlagToEnvVar(flag); 80941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const value = posix::GetEnv(env_var.c_str()); 8101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return value == NULL ? default_value : value; 8111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 8121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 8131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} // namespace internal 8141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} // namespace testing 815