1// Copyright 2008, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Author: wan@google.com (Zhanyong Wan)
31
32#include <gtest/internal/gtest-port.h>
33
34#include <limits.h>
35#ifdef GTEST_HAS_DEATH_TEST
36#include <regex.h>
37#endif  // GTEST_HAS_DEATH_TEST
38#include <stdlib.h>
39#include <stdio.h>
40
41#include <gtest/gtest-spi.h>
42#include <gtest/gtest-message.h>
43#include <gtest/internal/gtest-string.h>
44
45namespace testing {
46namespace internal {
47
48#ifdef GTEST_HAS_DEATH_TEST
49
50// Implements RE.  Currently only needed for death tests.
51
52RE::~RE() {
53  regfree(&regex_);
54  free(const_cast<char*>(pattern_));
55}
56
57// Returns true iff str contains regular expression re.
58bool RE::PartialMatch(const char* str, const RE& re) {
59  if (!re.is_valid_) return false;
60
61  regmatch_t match;
62  return regexec(&re.regex_, str, 1, &match, 0) == 0;
63}
64
65// Initializes an RE from its string representation.
66void RE::Init(const char* regex) {
67  pattern_ = strdup(regex);
68  is_valid_ = regcomp(&regex_, regex, REG_EXTENDED) == 0;
69  EXPECT_TRUE(is_valid_)
70      << "Regular expression \"" << regex
71      << "\" is not a valid POSIX Extended regular expression.";
72}
73
74#endif  // GTEST_HAS_DEATH_TEST
75
76// Logs a message at the given severity level.
77void GTestLog(GTestLogSeverity severity, const char* file,
78              int line, const char* msg) {
79  const char* const marker =
80      severity == GTEST_INFO ?    "[  INFO ]" :
81      severity == GTEST_WARNING ? "[WARNING]" :
82      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
83  fprintf(stderr, "\n%s %s:%d: %s\n", marker, file, line, msg);
84  if (severity == GTEST_FATAL) {
85    abort();
86  }
87}
88
89#ifdef GTEST_HAS_DEATH_TEST
90
91// Defines the stderr capturer.
92
93class CapturedStderr {
94 public:
95  // The ctor redirects stderr to a temporary file.
96  CapturedStderr() {
97    uncaptured_fd_ = dup(STDERR_FILENO);
98
99    char name_template[] = "captured_stderr.XXXXXX";
100    const int captured_fd = mkstemp(name_template);
101    filename_ = name_template;
102    fflush(NULL);
103    dup2(captured_fd, STDERR_FILENO);
104    close(captured_fd);
105  }
106
107  ~CapturedStderr() {
108    remove(filename_.c_str());
109  }
110
111  // Stops redirecting stderr.
112  void StopCapture() {
113    // Restores the original stream.
114    fflush(NULL);
115    dup2(uncaptured_fd_, STDERR_FILENO);
116    close(uncaptured_fd_);
117    uncaptured_fd_ = -1;
118  }
119
120  // Returns the name of the temporary file holding the stderr output.
121  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
122  // can use it here.
123  ::std::string filename() const { return filename_; }
124
125 private:
126  int uncaptured_fd_;
127  ::std::string filename_;
128};
129
130static CapturedStderr* g_captured_stderr = NULL;
131
132// Returns the size (in bytes) of a file.
133static size_t GetFileSize(FILE * file) {
134  fseek(file, 0, SEEK_END);
135  return static_cast<size_t>(ftell(file));
136}
137
138// Reads the entire content of a file as a string.
139// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
140// use it here.
141static ::std::string ReadEntireFile(FILE * file) {
142  const size_t file_size = GetFileSize(file);
143  char* const buffer = new char[file_size];
144
145  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
146  size_t bytes_read = 0;       // # of bytes read so far
147
148  fseek(file, 0, SEEK_SET);
149
150  // Keeps reading the file until we cannot read further or the
151  // pre-determined file size is reached.
152  do {
153    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
154    bytes_read += bytes_last_read;
155  } while (bytes_last_read > 0 && bytes_read < file_size);
156
157  const ::std::string content(buffer, buffer+bytes_read);
158  delete[] buffer;
159
160  return content;
161}
162
163// Starts capturing stderr.
164void CaptureStderr() {
165  if (g_captured_stderr != NULL) {
166    GTEST_LOG(FATAL, "Only one stderr capturer can exist at one time.");
167  }
168  g_captured_stderr = new CapturedStderr;
169}
170
171// Stops capturing stderr and returns the captured string.
172// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
173// use it here.
174::std::string GetCapturedStderr() {
175  g_captured_stderr->StopCapture();
176  FILE* const file = fopen(g_captured_stderr->filename().c_str(), "r");
177  const ::std::string content = ReadEntireFile(file);
178  fclose(file);
179
180  delete g_captured_stderr;
181  g_captured_stderr = NULL;
182
183  return content;
184}
185
186// A copy of all command line arguments.  Set by InitGoogleTest().
187::std::vector<String> g_argvs;
188
189// Returns the command line as a vector of strings.
190const ::std::vector<String>& GetArgvs() { return g_argvs; }
191
192#endif  // GTEST_HAS_DEATH_TEST
193
194// Returns the name of the environment variable corresponding to the
195// given flag.  For example, FlagToEnvVar("foo") will return
196// "GTEST_FOO" in the open-source version.
197static String FlagToEnvVar(const char* flag) {
198  const String full_flag = (Message() << GTEST_FLAG_PREFIX << flag).GetString();
199
200  Message env_var;
201  for (int i = 0; i != full_flag.GetLength(); i++) {
202    env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
203  }
204
205  return env_var.GetString();
206}
207
208// Reads and returns the Boolean environment variable corresponding to
209// the given flag; if it's not set, returns default_value.
210//
211// The value is considered true iff it's not "0".
212bool BoolFromGTestEnv(const char* flag, bool default_value) {
213  const String env_var = FlagToEnvVar(flag);
214  const char* const string_value = GetEnv(env_var.c_str());
215  return string_value == NULL ?
216      default_value : strcmp(string_value, "0") != 0;
217}
218
219// Parses 'str' for a 32-bit signed integer.  If successful, writes
220// the result to *value and returns true; otherwise leaves *value
221// unchanged and returns false.
222bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
223  // Parses the environment variable as a decimal integer.
224  char* end = NULL;
225  const long long_value = strtol(str, &end, 10);  // NOLINT
226
227  // Has strtol() consumed all characters in the string?
228  if (*end != '\0') {
229    // No - an invalid character was encountered.
230    Message msg;
231    msg << "WARNING: " << src_text
232        << " is expected to be a 32-bit integer, but actually"
233        << " has value \"" << str << "\".\n";
234    printf("%s", msg.GetString().c_str());
235    fflush(stdout);
236    return false;
237  }
238
239  // Is the parsed value in the range of an Int32?
240  const Int32 result = static_cast<Int32>(long_value);
241  if (long_value == LONG_MAX || long_value == LONG_MIN ||
242      // The parsed value overflows as a long.  (strtol() returns
243      // LONG_MAX or LONG_MIN when the input overflows.)
244      result != long_value
245      // The parsed value overflows as an Int32.
246      ) {
247    Message msg;
248    msg << "WARNING: " << src_text
249        << " is expected to be a 32-bit integer, but actually"
250        << " has value " << str << ", which overflows.\n";
251    printf("%s", msg.GetString().c_str());
252    fflush(stdout);
253    return false;
254  }
255
256  *value = result;
257  return true;
258}
259
260// Reads and returns a 32-bit integer stored in the environment
261// variable corresponding to the given flag; if it isn't set or
262// doesn't represent a valid 32-bit integer, returns default_value.
263Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
264  const String env_var = FlagToEnvVar(flag);
265  const char* const string_value = GetEnv(env_var.c_str());
266  if (string_value == NULL) {
267    // The environment variable is not set.
268    return default_value;
269  }
270
271  Int32 result = default_value;
272  if (!ParseInt32(Message() << "Environment variable " << env_var,
273                  string_value, &result)) {
274    printf("The default value %s is used.\n",
275           (Message() << default_value).GetString().c_str());
276    fflush(stdout);
277    return default_value;
278  }
279
280  return result;
281}
282
283// Reads and returns the string environment variable corresponding to
284// the given flag; if it's not set, returns default_value.
285const char* StringFromGTestEnv(const char* flag, const char* default_value) {
286  const String env_var = FlagToEnvVar(flag);
287  const char* const value = GetEnv(env_var.c_str());
288  return value == NULL ? default_value : value;
289}
290
291}  // namespace internal
292}  // namespace testing
293