1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Copyright 2008, Google Inc. 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// All rights reserved. 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Redistribution and use in source and binary forms, with or without 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// modification, are permitted provided that the following conditions are 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// met: 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// * Redistributions of source code must retain the above copyright 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// notice, this list of conditions and the following disclaimer. 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// * Redistributions in binary form must reproduce the above 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// copyright notice, this list of conditions and the following disclaimer 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// in the documentation and/or other materials provided with the 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// distribution. 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// * Neither the name of Google Inc. nor the names of its 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// contributors may be used to endorse or promote products derived from 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// this software without specific prior written permission. 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Author: wan@google.com (Zhanyong Wan) 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "gtest/internal/gtest-port.h" 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <limits.h> 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdlib.h> 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h> 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <string.h> 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_OS_WINDOWS_MOBILE 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# include <windows.h> // For TerminateProcess() 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif GTEST_OS_WINDOWS 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# include <io.h> 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# include <sys/stat.h> 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# include <unistd.h> 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // GTEST_OS_WINDOWS_MOBILE 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_OS_MAC 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# include <mach/mach_init.h> 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# include <mach/task.h> 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# include <mach/vm_map.h> 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // GTEST_OS_MAC 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "gtest/gtest-spi.h" 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "gtest/gtest-message.h" 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "gtest/internal/gtest-internal.h" 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "gtest/internal/gtest-string.h" 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Indicates that this translation unit is part of Google Test's 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// implementation. It must come before gtest-internal-inl.h is 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// included, or there will be a compiler error. This trick is to 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// prevent a user from accidentally including gtest-internal-inl.h in 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// his code. 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define GTEST_IMPLEMENTATION_ 1 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "src/gtest-internal-inl.h" 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef GTEST_IMPLEMENTATION_ 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace testing { 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace internal { 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(_MSC_VER) || defined(__BORLANDC__) 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// MSVC and C++Builder do not provide a definition of STDERR_FILENO. 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst int kStdOutFileno = 1; 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst int kStdErrFileno = 2; 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst int kStdOutFileno = STDOUT_FILENO; 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst int kStdErrFileno = STDERR_FILENO; 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // _MSC_VER 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_OS_MAC 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns the number of threads running in the process, or 0 to indicate that 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// we cannot detect it. 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsize_t GetThreadCount() { 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const task_t task = mach_task_self(); 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mach_msg_type_number_t thread_count; 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org thread_act_array_t thread_list; 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const kern_return_t status = task_threads(task, &thread_list, &thread_count); 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (status == KERN_SUCCESS) { 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // task_threads allocates resources in thread_list and we need to free them 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // to avoid leaks. 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vm_deallocate(task, 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org reinterpret_cast<vm_address_t>(thread_list), 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sizeof(thread_t) * thread_count); 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return static_cast<size_t>(thread_count); 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 0; 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsize_t GetThreadCount() { 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // There's no portable way to detect the number of threads, so we just 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // return 0 to indicate that we cannot detect it. 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 0; 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // GTEST_OS_MAC 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_USES_POSIX_RE 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Implements RE. Currently only needed for death tests. 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgRE::~RE() { 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (is_valid_) { 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // regfree'ing an invalid regex might crash because the content 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // of the regex is undefined. Since the regex's are essentially 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // the same, one cannot be valid (or invalid) without the other 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // being so too. 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org regfree(&partial_regex_); 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org regfree(&full_regex_); 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(const_cast<char*>(pattern_)); 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff regular expression re matches the entire str. 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool RE::FullMatch(const char* str, const RE& re) { 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!re.is_valid_) return false; 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org regmatch_t match; 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return regexec(&re.full_regex_, str, 1, &match, 0) == 0; 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff regular expression re matches a substring of str 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// (including str itself). 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool RE::PartialMatch(const char* str, const RE& re) { 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!re.is_valid_) return false; 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org regmatch_t match; 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Initializes an RE from its string representation. 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid RE::Init(const char* regex) { 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pattern_ = posix::StrDup(regex); 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Reserves enough bytes to hold the regular expression used for a 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // full match. 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const size_t full_regex_len = strlen(regex) + 10; 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char* const full_pattern = new char[full_regex_len]; 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org snprintf(full_pattern, full_regex_len, "^(%s)$", regex); 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We want to call regcomp(&partial_regex_, ...) even if the 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // previous expression returns false. Otherwise partial_regex_ may 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // not be properly initialized can may cause trouble when it's 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // freed. 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Some implementation of POSIX regex (e.g. on at least some 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // versions of Cygwin) doesn't accept the empty string as a valid 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // regex. We change it to an equivalent form "()" to be safe. 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (is_valid_) { 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* const partial_regex = (*regex == '\0') ? "()" : regex; 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org EXPECT_TRUE(is_valid_) 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "Regular expression \"" << regex 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "\" is not a valid POSIX Extended regular expression."; 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org delete[] full_pattern; 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif GTEST_USES_SIMPLE_RE 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff ch appears anywhere in str (excluding the 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// terminating '\0' character). 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool IsInSet(char ch, const char* str) { 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ch != '\0' && strchr(str, ch) != NULL; 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff ch belongs to the given classification. Unlike 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// similar functions in <ctype.h>, these aren't affected by the 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// current locale. 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool IsAsciiPunct(char ch) { 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool IsAsciiWordChar(char ch) { 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ('0' <= ch && ch <= '9') || ch == '_'; 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff "\\c" is a supported escape sequence. 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool IsValidEscape(char c) { 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff the given atom (specified by escaped and pattern) 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// matches ch. The result is undefined if the atom is invalid. 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool AtomMatchesChar(bool escaped, char pattern_char, char ch) { 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (escaped) { // "\\p" where p is pattern_char. 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (pattern_char) { 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'd': return IsAsciiDigit(ch); 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'D': return !IsAsciiDigit(ch); 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'f': return ch == '\f'; 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'n': return ch == '\n'; 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'r': return ch == '\r'; 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 's': return IsAsciiWhiteSpace(ch); 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'S': return !IsAsciiWhiteSpace(ch); 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 't': return ch == '\t'; 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'v': return ch == '\v'; 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'w': return IsAsciiWordChar(ch); 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 'W': return !IsAsciiWordChar(ch); 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return IsAsciiPunct(pattern_char) && pattern_char == ch; 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return (pattern_char == '.' && ch != '\n') || pattern_char == ch; 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Helper function used by ValidateRegex() to format error messages. 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgString FormatRegexSyntaxError(const char* regex, int index) { 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return (Message() << "Syntax error at index " << index 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << " in simple regular expression \"" << regex << "\": ").GetString(); 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Generates non-fatal failures and returns false if regex is invalid; 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// otherwise returns true. 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ValidateRegex(const char* regex) { 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (regex == NULL) { 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // TODO(wan@google.com): fix the source file location in the 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // assertion failures to match where the regex is used in user 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // code. 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ADD_FAILURE() << "NULL is not a valid simple regular expression."; 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool is_valid = true; 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // True iff ?, *, or + can follow the previous atom. 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool prev_repeatable = false; 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (int i = 0; regex[i]; i++) { 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (regex[i] == '\\') { // An escape sequence 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org i++; 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (regex[i] == '\0') { 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "'\\' cannot appear at the end."; 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!IsValidEscape(regex[i])) { 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "invalid escape sequence \"\\" << regex[i] << "\"."; 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid = false; 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prev_repeatable = true; 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { // Not an escape sequence. 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char ch = regex[i]; 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ch == '^' && i > 0) { 264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "'^' can only appear at the beginning."; 266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid = false; 267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (ch == '$' && regex[i + 1] != '\0') { 268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "'$' can only appear at the end."; 270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid = false; 271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (IsInSet(ch, "()[]{}|")) { 272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "'" << ch << "' is unsupported."; 274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid = false; 275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (IsRepeat(ch) && !prev_repeatable) { 276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ADD_FAILURE() << FormatRegexSyntaxError(regex, i) 277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "'" << ch << "' can only follow a repeatable token."; 278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid = false; 279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prev_repeatable = !IsInSet(ch, "^$?*+"); 282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return is_valid; 286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Matches a repeated regex atom followed by a valid simple regular 289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// expression. The regex atom is defined as c if escaped is false, 290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// or \c otherwise. repeat is the repetition meta character (?, *, 291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// or +). The behavior is undefined if str contains too many 292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// characters to be indexable by size_t, in which case the test will 293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// probably time out anyway. We are fine with this limitation as 294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// std::string has it too. 295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool MatchRepetitionAndRegexAtHead( 296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool escaped, char c, char repeat, const char* regex, 297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* str) { 298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const size_t min_count = (repeat == '+') ? 1 : 0; 299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const size_t max_count = (repeat == '?') ? 1 : 300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static_cast<size_t>(-1) - 1; 301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We cannot call numeric_limits::max() as it conflicts with the 302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // max() macro on Windows. 303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (size_t i = 0; i <= max_count; ++i) { 305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We know that the atom matches each of the first i characters in str. 306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (i >= min_count && MatchRegexAtHead(regex, str + i)) { 307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We have enough matches at the head, and the tail matches too. 308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Since we only care about *whether* the pattern matches str 309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // (as opposed to *how* it matches), there is no need to find a 310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // greedy match. 311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) 314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff regex matches a prefix of str. regex must be a 320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// valid simple regular expression and not start with "^", or the 321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// result is undefined. 322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool MatchRegexAtHead(const char* regex, const char* str) { 323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*regex == '\0') // An empty regex matches a prefix of anything. 324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // "$" only matches the end of a string. Note that regex being 327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // valid guarantees that there's nothing after "$" in it. 328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*regex == '$') 329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return *str == '\0'; 330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Is the first thing in regex an escape sequence? 332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const bool escaped = *regex == '\\'; 333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (escaped) 334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ++regex; 335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (IsRepeat(regex[1])) { 336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so 337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // here's an indirect recursion. It terminates as the regex gets 338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // shorter in each recursion. 339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return MatchRepetitionAndRegexAtHead( 340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org escaped, regex[0], regex[1], regex + 2, str); 341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // regex isn't empty, isn't "$", and doesn't start with a 343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // repetition. We match the first atom of regex with the first 344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // character of str and recurse. 345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && 346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org MatchRegexAtHead(regex + 1, str + 1); 347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff regex matches any substring of str. regex must be 351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// a valid simple regular expression, or the result is undefined. 352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// The algorithm is recursive, but the recursion depth doesn't exceed 354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// the regex length, so we won't need to worry about running out of 355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// stack space normally. In rare cases the time complexity can be 356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// exponential with respect to the regex length + the string length, 357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// but usually it's must faster (often close to linear). 358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool MatchRegexAnywhere(const char* regex, const char* str) { 359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (regex == NULL || str == NULL) 360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*regex == '^') 363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return MatchRegexAtHead(regex + 1, str); 364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // A successful match can be anywhere in str. 366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org do { 367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (MatchRegexAtHead(regex, str)) 368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } while (*str++ != '\0'); 370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Implements the RE class. 374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgRE::~RE() { 376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(const_cast<char*>(pattern_)); 377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(const_cast<char*>(full_pattern_)); 378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff regular expression re matches the entire str. 381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool RE::FullMatch(const char* str, const RE& re) { 382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); 383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns true iff regular expression re matches a substring of str 386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// (including str itself). 387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool RE::PartialMatch(const char* str, const RE& re) { 388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); 389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Initializes an RE from its string representation. 392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid RE::Init(const char* regex) { 393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pattern_ = full_pattern_ = NULL; 394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (regex != NULL) { 395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pattern_ = posix::StrDup(regex); 396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org is_valid_ = ValidateRegex(regex); 399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!is_valid_) { 400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // No need to calculate the full pattern when the regex is invalid. 401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const size_t len = strlen(regex); 405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Reserves enough bytes to hold the regular expression used for a 406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // full match: we need space to prepend a '^', append a '$', and 407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // terminate the string with '\0'. 408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char* buffer = static_cast<char*>(malloc(len + 3)); 409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org full_pattern_ = buffer; 410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*regex != '^') 412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. 413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We don't use snprintf or strncpy, as they trigger a warning when 415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // compiled with VC++ 8.0. 416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(buffer, regex, len); 417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buffer += len; 418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (len == 0 || regex[len - 1] != '$') 420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. 421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *buffer = '\0'; 423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // GTEST_USES_POSIX_RE 426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char kUnknownFile[] = "unknown file"; 428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Formats a source file path and a line number as they would appear 430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// in an error message from the compiler used to compile this code. 431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgGTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { 432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* const file_name = file == NULL ? kUnknownFile : file; 433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (line < 0) { 435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return String::Format("%s:", file_name).c_str(); 436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef _MSC_VER 438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return String::Format("%s(%d):", file_name, line).c_str(); 439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return String::Format("%s:%d:", file_name, line).c_str(); 441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // _MSC_VER 442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Formats a file location for compiler-independent XML output. 445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Although this function is not platform dependent, we put it next to 446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// FormatFileLocation in order to contrast the two functions. 447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Note that FormatCompilerIndependentFileLocation() does NOT append colon 448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// to the file location it produces, unlike FormatFileLocation(). 449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgGTEST_API_ ::std::string FormatCompilerIndependentFileLocation( 450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* file, int line) { 451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* const file_name = file == NULL ? kUnknownFile : file; 452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (line < 0) 454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return file_name; 455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return String::Format("%s:%d", file_name, line).c_str(); 457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgGTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) 461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org : severity_(severity) { 462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* const marker = 463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org severity == GTEST_INFO ? "[ INFO ]" : 464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org severity == GTEST_WARNING ? "[WARNING]" : 465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; 466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GetStream() << ::std::endl << marker << " " 467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << FormatFileLocation(file, line).c_str() << ": "; 468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. 471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgGTestLog::~GTestLog() { 472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GetStream() << ::std::endl; 473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (severity_ == GTEST_FATAL) { 474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fflush(stderr); 475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org posix::Abort(); 476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Disable Microsoft deprecation warnings for POSIX functions called from 479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// this class (creat, dup, dup2, and close) 480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef _MSC_VER 481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# pragma warning(push) 482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# pragma warning(disable: 4996) 483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // _MSC_VER 484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_HAS_STREAM_REDIRECTION 486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Object that captures an output stream (stdout/stderr). 488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass CapturedStream { 489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // The ctor redirects the stream to a temporary file. 491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { 492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# if GTEST_OS_WINDOWS 494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT 495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT 496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); 498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const UINT success = ::GetTempFileNameA(temp_dir_path, 499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "gtest_redir", 500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 0, // Generate unique file name. 501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org temp_file_path); 502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GTEST_CHECK_(success != 0) 503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << "Unable to create a temporary file in " << temp_dir_path; 504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); 505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " 506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << temp_file_path; 507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org filename_ = temp_file_path; 508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# else 509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // There's no guarantee that a test has write access to the 510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // current directory, so we create the temporary file in the /tmp 511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // directory instead. 512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char name_template[] = "/tmp/captured_stream.XXXXXX"; 513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const int captured_fd = mkstemp(name_template); 514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org filename_ = name_template; 515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# endif // GTEST_OS_WINDOWS 516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fflush(NULL); 517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org dup2(captured_fd, fd_); 518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org close(captured_fd); 519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ~CapturedStream() { 522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org remove(filename_.c_str()); 523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org String GetCapturedString() { 526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (uncaptured_fd_ != -1) { 527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Restores the original stream. 528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fflush(NULL); 529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org dup2(uncaptured_fd_, fd_); 530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org close(uncaptured_fd_); 531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uncaptured_fd_ = -1; 532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FILE* const file = posix::FOpen(filename_.c_str(), "r"); 535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const String content = ReadEntireFile(file); 536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org posix::FClose(file); 537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return content; 538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org private: 541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Reads the entire content of a file as a String. 542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static String ReadEntireFile(FILE* file); 543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Returns the size (in bytes) of a file. 545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static size_t GetFileSize(FILE* file); 546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const int fd_; // A stream to capture. 548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int uncaptured_fd_; 549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Name of the temporary file holding the stderr output. 550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ::std::string filename_; 551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); 553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns the size (in bytes) of a file. 556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsize_t CapturedStream::GetFileSize(FILE* file) { 557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fseek(file, 0, SEEK_END); 558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return static_cast<size_t>(ftell(file)); 559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Reads the entire content of a file as a string. 562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgString CapturedStream::ReadEntireFile(FILE* file) { 563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const size_t file_size = GetFileSize(file); 564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char* const buffer = new char[file_size]; 565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org size_t bytes_last_read = 0; // # of bytes read in the last fread() 567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org size_t bytes_read = 0; // # of bytes read so far 568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fseek(file, 0, SEEK_SET); 570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Keeps reading the file until we cannot read further or the 572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // pre-determined file size is reached. 573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org do { 574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); 575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bytes_read += bytes_last_read; 576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } while (bytes_last_read > 0 && bytes_read < file_size); 577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const String content(buffer, bytes_read); 579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org delete[] buffer; 580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return content; 582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# ifdef _MSC_VER 585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# pragma warning(pop) 586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# endif // _MSC_VER 587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic CapturedStream* g_captured_stderr = NULL; 589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic CapturedStream* g_captured_stdout = NULL; 590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Starts capturing an output stream (stdout/stderr). 592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { 593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*stream != NULL) { 594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GTEST_LOG_(FATAL) << "Only one " << stream_name 595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << " capturer can exist at a time."; 596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *stream = new CapturedStream(fd); 598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Stops capturing the output stream and returns the captured string. 601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgString GetCapturedStream(CapturedStream** captured_stream) { 602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const String content = (*captured_stream)->GetCapturedString(); 603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org delete *captured_stream; 605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *captured_stream = NULL; 606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return content; 608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Starts capturing stdout. 611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid CaptureStdout() { 612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); 613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Starts capturing stderr. 616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid CaptureStderr() { 617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); 618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Stops capturing stdout and returns the captured string. 621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgString GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); } 622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Stops capturing stderr and returns the captured string. 624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgString GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); } 625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // GTEST_HAS_STREAM_REDIRECTION 627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_HAS_DEATH_TEST 629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// A copy of all command line arguments. Set by InitGoogleTest(). 631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org::std::vector<String> g_argvs; 632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns the command line as a vector of strings. 634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst ::std::vector<String>& GetArgvs() { return g_argvs; } 635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // GTEST_HAS_DEATH_TEST 637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if GTEST_OS_WINDOWS_MOBILE 639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace posix { 640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid Abort() { 641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DebugBreak(); 642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org TerminateProcess(GetCurrentProcess(), 1); 643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // namespace posix 645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif // GTEST_OS_WINDOWS_MOBILE 646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Returns the name of the environment variable corresponding to the 648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// given flag. For example, FlagToEnvVar("foo") will return 649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// "GTEST_FOO" in the open-source version. 650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic String FlagToEnvVar(const char* flag) { 651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const String full_flag = 652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); 653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Message env_var; 655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (size_t i = 0; i != full_flag.length(); i++) { 656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org env_var << ToUpper(full_flag.c_str()[i]); 657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return env_var.GetString(); 660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Parses 'str' for a 32-bit signed integer. If successful, writes 663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// the result to *value and returns true; otherwise leaves *value 664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// unchanged and returns false. 665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool ParseInt32(const Message& src_text, const char* str, Int32* value) { 666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Parses the environment variable as a decimal integer. 667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char* end = NULL; 668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const long long_value = strtol(str, &end, 10); // NOLINT 669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Has strtol() consumed all characters in the string? 671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*end != '\0') { 672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // No - an invalid character was encountered. 673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Message msg; 674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org msg << "WARNING: " << src_text 675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << " is expected to be a 32-bit integer, but actually" 676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << " has value \"" << str << "\".\n"; 677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org printf("%s", msg.GetString().c_str()); 678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fflush(stdout); 679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Is the parsed value in the range of an Int32? 683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const Int32 result = static_cast<Int32>(long_value); 684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (long_value == LONG_MAX || long_value == LONG_MIN || 685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // The parsed value overflows as a long. (strtol() returns 686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // LONG_MAX or LONG_MIN when the input overflows.) 687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org result != long_value 688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // The parsed value overflows as an Int32. 689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ) { 690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Message msg; 691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org msg << "WARNING: " << src_text 692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << " is expected to be a 32-bit integer, but actually" 693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org << " has value " << str << ", which overflows.\n"; 694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org printf("%s", msg.GetString().c_str()); 695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fflush(stdout); 696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *value = result; 700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Reads and returns the Boolean environment variable corresponding to 704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// the given flag; if it's not set, returns default_value. 705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// The value is considered true iff it's not "0". 707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool BoolFromGTestEnv(const char* flag, bool default_value) { 708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const String env_var = FlagToEnvVar(flag); 709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* const string_value = posix::GetEnv(env_var.c_str()); 710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return string_value == NULL ? 711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default_value : strcmp(string_value, "0") != 0; 712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Reads and returns a 32-bit integer stored in the environment 715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// variable corresponding to the given flag; if it isn't set or 716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// doesn't represent a valid 32-bit integer, returns default_value. 717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgInt32 Int32FromGTestEnv(const char* flag, Int32 default_value) { 718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const String env_var = FlagToEnvVar(flag); 719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* const string_value = posix::GetEnv(env_var.c_str()); 720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (string_value == NULL) { 721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // The environment variable is not set. 722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return default_value; 723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Int32 result = default_value; 726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!ParseInt32(Message() << "Environment variable " << env_var, 727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org string_value, &result)) { 728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org printf("The default value %s is used.\n", 729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (Message() << default_value).GetString().c_str()); 730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fflush(stdout); 731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return default_value; 732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return result; 735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Reads and returns the string environment variable corresponding to 738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// the given flag; if it's not set, returns default_value. 739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char* StringFromGTestEnv(const char* flag, const char* default_value) { 740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const String env_var = FlagToEnvVar(flag); 741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char* const value = posix::GetEnv(env_var.c_str()); 742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return value == NULL ? default_value : value; 743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // namespace internal 746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // namespace testing 747