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 341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <limits.h> 351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <stdlib.h> 361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include <stdio.h> 3741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include <string.h> 381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_WINDOWS_MOBILE 4041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <windows.h> // For TerminateProcess() 4141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif GTEST_OS_WINDOWS 4241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <io.h> 4341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <sys/stat.h> 441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#else 4541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <unistd.h> 4641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_WINDOWS_MOBILE 471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_MAC 4941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/mach_init.h> 5041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/task.h> 5141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# include <mach/vm_map.h> 5241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_MAC 531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/gtest-spi.h" 5541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/gtest-message.h" 5641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-internal.h" 5741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#include "gtest/internal/gtest-string.h" 581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Indicates that this translation unit is part of Google Test's 601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// implementation. It must come before gtest-internal-inl.h is 611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// included, or there will be a compiler error. This trick is to 621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// prevent a user from accidentally including gtest-internal-inl.h in 631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// his code. 641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#define GTEST_IMPLEMENTATION_ 1 651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#include "src/gtest-internal-inl.h" 661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#undef GTEST_IMPLEMENTATION_ 671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catanianamespace testing { 691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catanianamespace internal { 701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if defined(_MSC_VER) || defined(__BORLANDC__) 7241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// MSVC and C++Builder do not provide a definition of STDERR_FILENO. 7341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst int kStdOutFileno = 1; 741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst int kStdErrFileno = 2; 751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#else 7641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst int kStdOutFileno = STDOUT_FILENO; 771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst int kStdErrFileno = STDERR_FILENO; 7841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // _MSC_VER 7941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 8041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_MAC 8141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 8241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Returns the number of threads running in the process, or 0 to indicate that 8341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// we cannot detect it. 8441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t GetThreadCount() { 8541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const task_t task = mach_task_self(); 8641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot mach_msg_type_number_t thread_count; 8741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot thread_act_array_t thread_list; 8841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const kern_return_t status = task_threads(task, &thread_list, &thread_count); 8941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (status == KERN_SUCCESS) { 9041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // task_threads allocates resources in thread_list and we need to free them 9141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // to avoid leaks. 9241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot vm_deallocate(task, 9341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot reinterpret_cast<vm_address_t>(thread_list), 9441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot sizeof(thread_t) * thread_count); 9541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return static_cast<size_t>(thread_count); 9641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } else { 9741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return 0; 9841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 9941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 10041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 10141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#else 10241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 10341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t GetThreadCount() { 10441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // There's no portable way to detect the number of threads, so we just 10541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // return 0 to indicate that we cannot detect it. 10641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return 0; 10741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 10841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 10941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_MAC 1101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#if GTEST_USES_POSIX_RE 1121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Implements RE. Currently only needed for death tests. 1141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1151be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaRE::~RE() { 11641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (is_valid_) { 11741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // regfree'ing an invalid regex might crash because the content 11841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // of the regex is undefined. Since the regex's are essentially 11941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // the same, one cannot be valid (or invalid) without the other 12041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // being so too. 12141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot regfree(&partial_regex_); 12241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot regfree(&full_regex_); 12341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 1241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania free(const_cast<char*>(pattern_)); 1251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches the entire str. 1281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::FullMatch(const char* str, const RE& re) { 1291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!re.is_valid_) return false; 1301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania regmatch_t match; 1321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return regexec(&re.full_regex_, str, 1, &match, 0) == 0; 1331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches a substring of str 1361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (including str itself). 1371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::PartialMatch(const char* str, const RE& re) { 1381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!re.is_valid_) return false; 1391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania regmatch_t match; 1411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; 1421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Initializes an RE from its string representation. 1451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniavoid RE::Init(const char* regex) { 14641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot pattern_ = posix::StrDup(regex); 1471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Reserves enough bytes to hold the regular expression used for a 1491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // full match. 1501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t full_regex_len = strlen(regex) + 10; 1511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* const full_pattern = new char[full_regex_len]; 1521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania snprintf(full_pattern, full_regex_len, "^(%s)$", regex); 1541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; 1551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We want to call regcomp(&partial_regex_, ...) even if the 1561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // previous expression returns false. Otherwise partial_regex_ may 1571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // not be properly initialized can may cause trouble when it's 1581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // freed. 1591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // 1601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Some implementation of POSIX regex (e.g. on at least some 1611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // versions of Cygwin) doesn't accept the empty string as a valid 1621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // regex. We change it to an equivalent form "()" to be safe. 16341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (is_valid_) { 16441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const partial_regex = (*regex == '\0') ? "()" : regex; 16541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; 16641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 1671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania EXPECT_TRUE(is_valid_) 1681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "Regular expression \"" << regex 1691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "\" is not a valid POSIX Extended regular expression."; 1701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania delete[] full_pattern; 1721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#elif GTEST_USES_SIMPLE_RE 1751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff ch appears anywhere in str (excluding the 1771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// terminating '\0' character). 1781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsInSet(char ch, const char* str) { 1791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return ch != '\0' && strchr(str, ch) != NULL; 1801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff ch belongs to the given classification. Unlike 1831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// similar functions in <ctype.h>, these aren't affected by the 1841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// current locale. 18541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } 18641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiPunct(char ch) { 1871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); 1881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } 19041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } 19141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotbool IsAsciiWordChar(char ch) { 1921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || 1931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ('0' <= ch && ch <= '9') || ch == '_'; 1941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 1951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 1961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff "\\c" is a supported escape sequence. 1971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool IsValidEscape(char c) { 19841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); 1991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff the given atom (specified by escaped and pattern) 2021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// matches ch. The result is undefined if the atom is invalid. 2031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool AtomMatchesChar(bool escaped, char pattern_char, char ch) { 2041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (escaped) { // "\\p" where p is pattern_char. 2051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania switch (pattern_char) { 20641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'd': return IsAsciiDigit(ch); 20741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'D': return !IsAsciiDigit(ch); 2081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'f': return ch == '\f'; 2091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'n': return ch == '\n'; 2101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'r': return ch == '\r'; 21141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 's': return IsAsciiWhiteSpace(ch); 21241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'S': return !IsAsciiWhiteSpace(ch); 2131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 't': return ch == '\t'; 2141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania case 'v': return ch == '\v'; 21541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'w': return IsAsciiWordChar(ch); 21641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot case 'W': return !IsAsciiWordChar(ch); 2171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 21841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return IsAsciiPunct(pattern_char) && pattern_char == ch; 2191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return (pattern_char == '.' && ch != '\n') || pattern_char == ch; 2221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Helper function used by ValidateRegex() to format error messages. 2251be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaString FormatRegexSyntaxError(const char* regex, int index) { 2261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return (Message() << "Syntax error at index " << index 2271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " in simple regular expression \"" << regex << "\": ").GetString(); 2281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Generates non-fatal failures and returns false if regex is invalid; 2311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// otherwise returns true. 2321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool ValidateRegex(const char* regex) { 2331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex == NULL) { 2341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // TODO(wan@google.com): fix the source file location in the 2351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // assertion failures to match where the regex is used in user 2361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // code. 2371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << "NULL is not a valid simple regular expression."; 2381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 2391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bool is_valid = true; 2421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // True iff ?, *, or + can follow the previous atom. 2441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bool prev_repeatable = false; 2451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania for (int i = 0; regex[i]; i++) { 2461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex[i] == '\\') { // An escape sequence 2471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania i++; 2481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex[i] == '\0') { 2491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) 2501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'\\' cannot appear at the end."; 2511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 2521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!IsValidEscape(regex[i])) { 2551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) 2561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "invalid escape sequence \"\\" << regex[i] << "\"."; 2571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania prev_repeatable = true; 2601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else { // Not an escape sequence. 2611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const char ch = regex[i]; 2621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (ch == '^' && i > 0) { 2641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 2651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'^' can only appear at the beginning."; 2661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else if (ch == '$' && regex[i + 1] != '\0') { 2681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 2691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'$' can only appear at the end."; 2701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else if (IsInSet(ch, "()[]{}|")) { 2721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 2731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'" << ch << "' is unsupported."; 2741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else if (IsRepeat(ch) && !prev_repeatable) { 2761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 2771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << "'" << ch << "' can only follow a repeatable token."; 2781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid = false; 2791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania prev_repeatable = !IsInSet(ch, "^$?*+"); 2821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 2841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return is_valid; 2861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 2871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 2881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Matches a repeated regex atom followed by a valid simple regular 2891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// expression. The regex atom is defined as c if escaped is false, 2901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// or \c otherwise. repeat is the repetition meta character (?, *, 2911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// or +). The behavior is undefined if str contains too many 2921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// characters to be indexable by size_t, in which case the test will 2931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// probably time out anyway. We are fine with this limitation as 2941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// std::string has it too. 2951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRepetitionAndRegexAtHead( 2961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bool escaped, char c, char repeat, const char* regex, 2971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const char* str) { 2981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t min_count = (repeat == '+') ? 1 : 0; 2991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t max_count = (repeat == '?') ? 1 : 3001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania static_cast<size_t>(-1) - 1; 3011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We cannot call numeric_limits::max() as it conflicts with the 3021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // max() macro on Windows. 3031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania for (size_t i = 0; i <= max_count; ++i) { 3051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We know that the atom matches each of the first i characters in str. 3061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (i >= min_count && MatchRegexAtHead(regex, str + i)) { 3071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We have enough matches at the head, and the tail matches too. 3081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Since we only care about *whether* the pattern matches str 3091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // (as opposed to *how* it matches), there is no need to find a 3101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // greedy match. 3111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 3121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) 3141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regex matches a prefix of str. regex must be a 3201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// valid simple regular expression and not start with "^", or the 3211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// result is undefined. 3221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRegexAtHead(const char* regex, const char* str) { 3231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex == '\0') // An empty regex matches a prefix of anything. 3241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 3251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // "$" only matches the end of a string. Note that regex being 3271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // valid guarantees that there's nothing after "$" in it. 3281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex == '$') 3291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return *str == '\0'; 3301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Is the first thing in regex an escape sequence? 3321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const bool escaped = *regex == '\\'; 3331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (escaped) 3341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ++regex; 3351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (IsRepeat(regex[1])) { 3361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so 3371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // here's an indirect recursion. It terminates as the regex gets 3381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // shorter in each recursion. 3391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return MatchRepetitionAndRegexAtHead( 3401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania escaped, regex[0], regex[1], regex + 2, str); 3411be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } else { 3421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // regex isn't empty, isn't "$", and doesn't start with a 3431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // repetition. We match the first atom of regex with the first 3441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // character of str and recurse. 3451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && 3461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania MatchRegexAtHead(regex + 1, str + 1); 3471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regex matches any substring of str. regex must be 3511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// a valid simple regular expression, or the result is undefined. 3521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 3531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// The algorithm is recursive, but the recursion depth doesn't exceed 3541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the regex length, so we won't need to worry about running out of 3551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// stack space normally. In rare cases the time complexity can be 3561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// exponential with respect to the regex length + the string length, 3571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// but usually it's must faster (often close to linear). 3581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool MatchRegexAnywhere(const char* regex, const char* str) { 3591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex == NULL || str == NULL) 3601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex == '^') 3631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return MatchRegexAtHead(regex + 1, str); 3641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // A successful match can be anywhere in str. 3661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania do { 3671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (MatchRegexAtHead(regex, str)) 3681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 3691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } while (*str++ != '\0'); 3701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 3711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Implements the RE class. 3741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3751be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaRE::~RE() { 3761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania free(const_cast<char*>(pattern_)); 3771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania free(const_cast<char*>(full_pattern_)); 3781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches the entire str. 3811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::FullMatch(const char* str, const RE& re) { 3821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); 3831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns true iff regular expression re matches a substring of str 3861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// (including str itself). 3871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool RE::PartialMatch(const char* str, const RE& re) { 3881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); 3891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 3901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Initializes an RE from its string representation. 3921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniavoid RE::Init(const char* regex) { 3931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania pattern_ = full_pattern_ = NULL; 3941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (regex != NULL) { 39541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot pattern_ = posix::StrDup(regex); 3961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 3971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 3981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania is_valid_ = ValidateRegex(regex); 3991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!is_valid_) { 4001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // No need to calculate the full pattern when the regex is invalid. 4011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return; 4021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 4031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t len = strlen(regex); 4051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Reserves enough bytes to hold the regular expression used for a 4061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // full match: we need space to prepend a '^', append a '$', and 4071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // terminate the string with '\0'. 4081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* buffer = static_cast<char*>(malloc(len + 3)); 4091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania full_pattern_ = buffer; 4101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*regex != '^') 4121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. 4131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // We don't use snprintf or strncpy, as they trigger a warning when 4151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // compiled with VC++ 8.0. 4161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania memcpy(buffer, regex, len); 4171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania buffer += len; 4181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (len == 0 || regex[len - 1] != '$') 4201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. 4211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *buffer = '\0'; 4231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 4241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif // GTEST_USES_POSIX_RE 4261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 42741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotconst char kUnknownFile[] = "unknown file"; 42841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 42941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Formats a source file path and a line number as they would appear 43041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// in an error message from the compiler used to compile this code. 43141d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { 43241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const file_name = file == NULL ? kUnknownFile : file; 43341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 43441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (line < 0) { 43541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return String::Format("%s:", file_name).c_str(); 43641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 43741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#ifdef _MSC_VER 43841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return String::Format("%s(%d):", file_name, line).c_str(); 43941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#else 44041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return String::Format("%s:%d:", file_name, line).c_str(); 44141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // _MSC_VER 44241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 44341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 44441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Formats a file location for compiler-independent XML output. 44541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Although this function is not platform dependent, we put it next to 44641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// FormatFileLocation in order to contrast the two functions. 44741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Note that FormatCompilerIndependentFileLocation() does NOT append colon 44841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// to the file location it produces, unlike FormatFileLocation(). 44941d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTEST_API_ ::std::string FormatCompilerIndependentFileLocation( 45041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* file, int line) { 45141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const file_name = file == NULL ? kUnknownFile : file; 45241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 45341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (line < 0) 45441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return file_name; 45541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot else 45641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return String::Format("%s:%d", file_name, line).c_str(); 45741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 45841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 45941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 46041d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) 46141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot : severity_(severity) { 4621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const char* const marker = 4631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania severity == GTEST_INFO ? "[ INFO ]" : 4641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania severity == GTEST_WARNING ? "[WARNING]" : 4651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; 46641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GetStream() << ::std::endl << marker << " " 46741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << FormatFileLocation(file, line).c_str() << ": "; 4681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 4691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 47041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. 47141d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotGTestLog::~GTestLog() { 47241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GetStream() << ::std::endl; 47341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (severity_ == GTEST_FATAL) { 47441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot fflush(stderr); 47541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot posix::Abort(); 47641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 47741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 4781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Disable Microsoft deprecation warnings for POSIX functions called from 4791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// this class (creat, dup, dup2, and close) 4801be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#ifdef _MSC_VER 48141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(push) 48241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(disable: 4996) 4831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif // _MSC_VER 4841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 48541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_HAS_STREAM_REDIRECTION 4861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 48741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Object that captures an output stream (stdout/stderr). 48841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotclass CapturedStream { 4891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania public: 49041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // The ctor redirects the stream to a temporary file. 49141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { 4921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 49341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# if GTEST_OS_WINDOWS 4941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT 4951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT 4961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 4971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); 49841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const UINT success = ::GetTempFileNameA(temp_dir_path, 49941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot "gtest_redir", 50041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 0, // Generate unique file name. 50141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot temp_file_path); 50241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_CHECK_(success != 0) 50341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << "Unable to create a temporary file in " << temp_dir_path; 5041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); 50541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " 50641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << temp_file_path; 5071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania filename_ = temp_file_path; 50841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// ANDROID 50941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#elif GTEST_OS_LINUX_ANDROID 510344e5f3db17615cc853073a02968a603efd39109Stephen Hines // Get $EXTERNAL_STORAGE from the environment, since this can change 511d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes // for shell users (fallback is /data/nativetest, for emulator users). 512d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes ::std::string external_storage = "/data/nativetest"; 513344e5f3db17615cc853073a02968a603efd39109Stephen Hines char *sdcard_path = getenv("EXTERNAL_STORAGE"); 514d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes if (sdcard_path != NULL) { 515d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes // Check that $EXTERNAL_STORAGE exists and is writable before trying to use it. 516d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes struct stat sb; 517d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes if (stat(sdcard_path, &sb) != -1) { 518d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes if ((sb.st_mode & S_IWUSR) != 0) { 519d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes external_storage = sdcard_path; 520d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes } 521d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes } 522344e5f3db17615cc853073a02968a603efd39109Stephen Hines } 523344e5f3db17615cc853073a02968a603efd39109Stephen Hines external_storage += "/captured_stderr.XXXXXX"; 524344e5f3db17615cc853073a02968a603efd39109Stephen Hines char *name_template = strdup(external_storage.c_str()); 52584190c7c1f1b899ad83fdd8e110bde08ad281534Nicolas Catania const int captured_fd = mkstemp(name_template); 526d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " 527d10596bd14e5abcdaa7fa5ebdb55a883a80c9406Elliott Hughes << name_template; 52884190c7c1f1b899ad83fdd8e110bde08ad281534Nicolas Catania filename_ = name_template; 529344e5f3db17615cc853073a02968a603efd39109Stephen Hines free(name_template); 530344e5f3db17615cc853073a02968a603efd39109Stephen Hines name_template = NULL; 53141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// END ANDROID 53241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# else 5331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // There's no guarantee that a test has write access to the 5341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // current directory, so we create the temporary file in the /tmp 5351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // directory instead. 53641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot char name_template[] = "/tmp/captured_stream.XXXXXX"; 5371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const int captured_fd = mkstemp(name_template); 5381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania filename_ = name_template; 53941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# endif // GTEST_OS_WINDOWS 5401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(NULL); 54141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot dup2(captured_fd, fd_); 5421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania close(captured_fd); 5431be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 5441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 54541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot ~CapturedStream() { 5461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania remove(filename_.c_str()); 5471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 5481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 54941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot String GetCapturedString() { 55041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (uncaptured_fd_ != -1) { 55141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // Restores the original stream. 55241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot fflush(NULL); 55341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot dup2(uncaptured_fd_, fd_); 55441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot close(uncaptured_fd_); 55541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot uncaptured_fd_ = -1; 55641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 5571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 55841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot FILE* const file = posix::FOpen(filename_.c_str(), "r"); 55941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const String content = ReadEntireFile(file); 56041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot posix::FClose(file); 56141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot return content; 56241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot } 5631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania private: 56541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // Reads the entire content of a file as a String. 56641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot static String ReadEntireFile(FILE* file); 56741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 56841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // Returns the size (in bytes) of a file. 56941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot static size_t GetFileSize(FILE* file); 57041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 57141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const int fd_; // A stream to capture. 5721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania int uncaptured_fd_; 57341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot // Name of the temporary file holding the stderr output. 5741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ::std::string filename_; 5751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 57641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); 57741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot}; 5781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5791be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the size (in bytes) of a file. 58041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotsize_t CapturedStream::GetFileSize(FILE* file) { 5811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fseek(file, 0, SEEK_END); 5821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return static_cast<size_t>(ftell(file)); 5831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 5841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads the entire content of a file as a string. 58641d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString CapturedStream::ReadEntireFile(FILE* file) { 5871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const size_t file_size = GetFileSize(file); 5881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* const buffer = new char[file_size]; 5891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania size_t bytes_last_read = 0; // # of bytes read in the last fread() 5911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania size_t bytes_read = 0; // # of bytes read so far 5921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fseek(file, 0, SEEK_SET); 5941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 5951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Keeps reading the file until we cannot read further or the 5961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // pre-determined file size is reached. 5971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania do { 5981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); 5991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania bytes_read += bytes_last_read; 6001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } while (bytes_last_read > 0 && bytes_read < file_size); 6011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 60241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const String content(buffer, bytes_read); 6031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania delete[] buffer; 6041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return content; 6061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 60841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# ifdef _MSC_VER 60941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# pragma warning(pop) 61041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot# endif // _MSC_VER 61141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 61241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CapturedStream* g_captured_stderr = NULL; 61341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotstatic CapturedStream* g_captured_stdout = NULL; 61441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 61541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing an output stream (stdout/stderr). 61641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { 61741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot if (*stream != NULL) { 61841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot GTEST_LOG_(FATAL) << "Only one " << stream_name 61941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot << " capturer can exist at a time."; 6201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 62141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot *stream = new CapturedStream(fd); 6221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 62441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing the output stream and returns the captured string. 62541d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString GetCapturedStream(CapturedStream** captured_stream) { 62641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const String content = (*captured_stream)->GetCapturedString(); 6271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 62841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot delete *captured_stream; 62941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot *captured_stream = NULL; 6301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return content; 6321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6331be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 63441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing stdout. 63541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStdout() { 63641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); 63741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 63841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 63941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Starts capturing stderr. 64041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid CaptureStderr() { 64141d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); 64241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} 64341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 64441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing stdout and returns the captured string. 64541d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); } 64641d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 64741d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot// Stops capturing stderr and returns the captured string. 64841d0579e8de9ef4ff178fc4991043c61a19943f7Brett ChabotString GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); } 64941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot 65041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_HAS_STREAM_REDIRECTION 6511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#if GTEST_HAS_DEATH_TEST 6531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// A copy of all command line arguments. Set by InitGoogleTest(). 6551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania::std::vector<String> g_argvs; 6561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the command line as a vector of strings. 6581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst ::std::vector<String>& GetArgvs() { return g_argvs; } 6591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania#endif // GTEST_HAS_DEATH_TEST 6611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 66241d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#if GTEST_OS_WINDOWS_MOBILE 66341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotnamespace posix { 66441d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabotvoid Abort() { 6651be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania DebugBreak(); 6661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania TerminateProcess(GetCurrentProcess(), 1); 6671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 66841d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot} // namespace posix 66941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot#endif // GTEST_OS_WINDOWS_MOBILE 6701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6711be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Returns the name of the environment variable corresponding to the 6721be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// given flag. For example, FlagToEnvVar("foo") will return 6731be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// "GTEST_FOO" in the open-source version. 6741be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniastatic String FlagToEnvVar(const char* flag) { 6751be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const String full_flag = 6761be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); 6771be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6781be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Message env_var; 67941d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot for (size_t i = 0; i != full_flag.length(); i++) { 68041d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot env_var << ToUpper(full_flag.c_str()[i]); 6811be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 6821be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6831be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return env_var.GetString(); 6841be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 6851be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6861be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Parses 'str' for a 32-bit signed integer. If successful, writes 6871be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the result to *value and returns true; otherwise leaves *value 6881be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// unchanged and returns false. 6891be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool ParseInt32(const Message& src_text, const char* str, Int32* value) { 6901be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Parses the environment variable as a decimal integer. 6911be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania char* end = NULL; 6921be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const long long_value = strtol(str, &end, 10); // NOLINT 6931be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 6941be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Has strtol() consumed all characters in the string? 6951be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (*end != '\0') { 6961be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // No - an invalid character was encountered. 6971be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Message msg; 6981be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania msg << "WARNING: " << src_text 6991be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " is expected to be a 32-bit integer, but actually" 7001be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " has value \"" << str << "\".\n"; 7011be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania printf("%s", msg.GetString().c_str()); 7021be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(stdout); 7031be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 7041be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7051be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7061be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // Is the parsed value in the range of an Int32? 7071be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const Int32 result = static_cast<Int32>(long_value); 7081be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (long_value == LONG_MAX || long_value == LONG_MIN || 7091be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // The parsed value overflows as a long. (strtol() returns 7101be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // LONG_MAX or LONG_MIN when the input overflows.) 7111be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania result != long_value 7121be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // The parsed value overflows as an Int32. 7131be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania ) { 7141be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Message msg; 7151be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania msg << "WARNING: " << src_text 7161be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " is expected to be a 32-bit integer, but actually" 7171be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania << " has value " << str << ", which overflows.\n"; 7181be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania printf("%s", msg.GetString().c_str()); 7191be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(stdout); 7201be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return false; 7211be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7221be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7231be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania *value = result; 7241be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return true; 7251be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 7261be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7271be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns the Boolean environment variable corresponding to 7281be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the given flag; if it's not set, returns default_value. 7291be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// 7301be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// The value is considered true iff it's not "0". 7311be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniabool BoolFromGTestEnv(const char* flag, bool default_value) { 7321be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const String env_var = FlagToEnvVar(flag); 73341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const string_value = posix::GetEnv(env_var.c_str()); 7341be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return string_value == NULL ? 7351be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania default_value : strcmp(string_value, "0") != 0; 7361be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 7371be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7381be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns a 32-bit integer stored in the environment 7391be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// variable corresponding to the given flag; if it isn't set or 7401be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// doesn't represent a valid 32-bit integer, returns default_value. 7411be2c9def7187e4e643c00a31dd9986395795d7dNicolas CataniaInt32 Int32FromGTestEnv(const char* flag, Int32 default_value) { 7421be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const String env_var = FlagToEnvVar(flag); 74341d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const string_value = posix::GetEnv(env_var.c_str()); 7441be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (string_value == NULL) { 7451be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania // The environment variable is not set. 7461be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return default_value; 7471be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7481be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7491be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania Int32 result = default_value; 7501be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania if (!ParseInt32(Message() << "Environment variable " << env_var, 7511be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania string_value, &result)) { 7521be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania printf("The default value %s is used.\n", 7531be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania (Message() << default_value).GetString().c_str()); 7541be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania fflush(stdout); 7551be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return default_value; 7561be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania } 7571be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7581be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return result; 7591be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 7601be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7611be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// Reads and returns the string environment variable corresponding to 7621be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania// the given flag; if it's not set, returns default_value. 7631be2c9def7187e4e643c00a31dd9986395795d7dNicolas Cataniaconst char* StringFromGTestEnv(const char* flag, const char* default_value) { 7641be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania const String env_var = FlagToEnvVar(flag); 76541d0579e8de9ef4ff178fc4991043c61a19943f7Brett Chabot const char* const value = posix::GetEnv(env_var.c_str()); 7661be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania return value == NULL ? default_value : value; 7671be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} 7681be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania 7691be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} // namespace internal 7701be2c9def7187e4e643c00a31dd9986395795d7dNicolas Catania} // namespace testing 771