1
// Copyright 2008, Google Inc.
2
// All rights reserved.
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
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
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.
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.
30
// Author: wan@google.com (Zhanyong Wan)
32
#include "gtest/internal/gtest-port.h"
39
#if GTEST_OS_WINDOWS_MOBILE
40
# include <windows.h> // For TerminateProcess()
41
#elif GTEST_OS_WINDOWS
43
# include <sys/stat.h>
46
#endif // GTEST_OS_WINDOWS_MOBILE
49
# include <mach/mach_init.h>
50
# include <mach/task.h>
51
# include <mach/vm_map.h>
52
#endif // GTEST_OS_MAC
56
# include <sys/procfs.h>
57
#endif // GTEST_OS_QNX
59
#include "gtest/gtest-spi.h"
60
#include "gtest/gtest-message.h"
61
#include "gtest/internal/gtest-internal.h"
62
#include "gtest/internal/gtest-string.h"
64
// Indicates that this translation unit is part of Google Test's
65
// implementation. It must come before gtest-internal-inl.h is
66
// included, or there will be a compiler error. This trick is to
67
// prevent a user from accidentally including gtest-internal-inl.h in
69
#define GTEST_IMPLEMENTATION_ 1
70
#include "src/gtest-internal-inl.h"
71
#undef GTEST_IMPLEMENTATION_
76
#if defined(_MSC_VER) || defined(__BORLANDC__)
77
// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
78
const int kStdOutFileno = 1;
79
const int kStdErrFileno = 2;
81
const int kStdOutFileno = STDOUT_FILENO;
82
const int kStdErrFileno = STDERR_FILENO;
87
// Returns the number of threads running in the process, or 0 to indicate that
88
// we cannot detect it.
89
size_t GetThreadCount() {
90
const task_t task = mach_task_self();
91
mach_msg_type_number_t thread_count;
92
thread_act_array_t thread_list;
93
const kern_return_t status = task_threads(task, &thread_list, &thread_count);
94
if (status == KERN_SUCCESS) {
95
// task_threads allocates resources in thread_list and we need to free them
98
reinterpret_cast<vm_address_t>(thread_list),
99
sizeof(thread_t) * thread_count);
100
return static_cast<size_t>(thread_count);
108
// Returns the number of threads running in the process, or 0 to indicate that
109
// we cannot detect it.
110
size_t GetThreadCount() {
111
const int fd = open("/proc/self/as", O_RDONLY);
115
procfs_info process_info;
117
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
120
return static_cast<size_t>(process_info.num_threads);
128
size_t GetThreadCount() {
129
// There's no portable way to detect the number of threads, so we just
130
// return 0 to indicate that we cannot detect it.
134
#endif // GTEST_OS_MAC
136
#if GTEST_USES_POSIX_RE
138
// Implements RE. Currently only needed for death tests.
142
// regfree'ing an invalid regex might crash because the content
143
// of the regex is undefined. Since the regex's are essentially
144
// the same, one cannot be valid (or invalid) without the other
146
regfree(&partial_regex_);
147
regfree(&full_regex_);
149
free(const_cast<char*>(pattern_));
152
// Returns true iff regular expression re matches the entire str.
153
bool RE::FullMatch(const char* str, const RE& re) {
154
if (!re.is_valid_) return false;
157
return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
160
// Returns true iff regular expression re matches a substring of str
161
// (including str itself).
162
bool RE::PartialMatch(const char* str, const RE& re) {
163
if (!re.is_valid_) return false;
166
return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
169
// Initializes an RE from its string representation.
170
void RE::Init(const char* regex) {
171
pattern_ = posix::StrDup(regex);
173
// Reserves enough bytes to hold the regular expression used for a
175
const size_t full_regex_len = strlen(regex) + 10;
176
char* const full_pattern = new char[full_regex_len];
178
snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
179
is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
180
// We want to call regcomp(&partial_regex_, ...) even if the
181
// previous expression returns false. Otherwise partial_regex_ may
182
// not be properly initialized can may cause trouble when it's
185
// Some implementation of POSIX regex (e.g. on at least some
186
// versions of Cygwin) doesn't accept the empty string as a valid
187
// regex. We change it to an equivalent form "()" to be safe.
189
const char* const partial_regex = (*regex == '\0') ? "()" : regex;
190
is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
192
EXPECT_TRUE(is_valid_)
193
<< "Regular expression \"" << regex
194
<< "\" is not a valid POSIX Extended regular expression.";
196
delete[] full_pattern;
199
#elif GTEST_USES_SIMPLE_RE
201
// Returns true iff ch appears anywhere in str (excluding the
202
// terminating '\0' character).
203
bool IsInSet(char ch, const char* str) {
204
return ch != '\0' && strchr(str, ch) != NULL;
207
// Returns true iff ch belongs to the given classification. Unlike
208
// similar functions in <ctype.h>, these aren't affected by the
210
bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
211
bool IsAsciiPunct(char ch) {
212
return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
214
bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
215
bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
216
bool IsAsciiWordChar(char ch) {
217
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
218
('0' <= ch && ch <= '9') || ch == '_';
221
// Returns true iff "\\c" is a supported escape sequence.
222
bool IsValidEscape(char c) {
223
return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
226
// Returns true iff the given atom (specified by escaped and pattern)
227
// matches ch. The result is undefined if the atom is invalid.
228
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
229
if (escaped) { // "\\p" where p is pattern_char.
230
switch (pattern_char) {
231
case 'd': return IsAsciiDigit(ch);
232
case 'D': return !IsAsciiDigit(ch);
233
case 'f': return ch == '\f';
234
case 'n': return ch == '\n';
235
case 'r': return ch == '\r';
236
case 's': return IsAsciiWhiteSpace(ch);
237
case 'S': return !IsAsciiWhiteSpace(ch);
238
case 't': return ch == '\t';
239
case 'v': return ch == '\v';
240
case 'w': return IsAsciiWordChar(ch);
241
case 'W': return !IsAsciiWordChar(ch);
243
return IsAsciiPunct(pattern_char) && pattern_char == ch;
246
return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
249
// Helper function used by ValidateRegex() to format error messages.
250
std::string FormatRegexSyntaxError(const char* regex, int index) {
251
return (Message() << "Syntax error at index " << index
252
<< " in simple regular expression \"" << regex << "\": ").GetString();
255
// Generates non-fatal failures and returns false if regex is invalid;
256
// otherwise returns true.
257
bool ValidateRegex(const char* regex) {
259
// TODO(wan@google.com): fix the source file location in the
260
// assertion failures to match where the regex is used in user
262
ADD_FAILURE() << "NULL is not a valid simple regular expression.";
266
bool is_valid = true;
268
// True iff ?, *, or + can follow the previous atom.
269
bool prev_repeatable = false;
270
for (int i = 0; regex[i]; i++) {
271
if (regex[i] == '\\') { // An escape sequence
273
if (regex[i] == '\0') {
274
ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
275
<< "'\\' cannot appear at the end.";
279
if (!IsValidEscape(regex[i])) {
280
ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
281
<< "invalid escape sequence \"\\" << regex[i] << "\".";
284
prev_repeatable = true;
285
} else { // Not an escape sequence.
286
const char ch = regex[i];
288
if (ch == '^' && i > 0) {
289
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
290
<< "'^' can only appear at the beginning.";
292
} else if (ch == '$' && regex[i + 1] != '\0') {
293
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
294
<< "'$' can only appear at the end.";
296
} else if (IsInSet(ch, "()[]{}|")) {
297
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
298
<< "'" << ch << "' is unsupported.";
300
} else if (IsRepeat(ch) && !prev_repeatable) {
301
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
302
<< "'" << ch << "' can only follow a repeatable token.";
306
prev_repeatable = !IsInSet(ch, "^$?*+");
313
// Matches a repeated regex atom followed by a valid simple regular
314
// expression. The regex atom is defined as c if escaped is false,
315
// or \c otherwise. repeat is the repetition meta character (?, *,
316
// or +). The behavior is undefined if str contains too many
317
// characters to be indexable by size_t, in which case the test will
318
// probably time out anyway. We are fine with this limitation as
319
// std::string has it too.
320
bool MatchRepetitionAndRegexAtHead(
321
bool escaped, char c, char repeat, const char* regex,
323
const size_t min_count = (repeat == '+') ? 1 : 0;
324
const size_t max_count = (repeat == '?') ? 1 :
325
static_cast<size_t>(-1) - 1;
326
// We cannot call numeric_limits::max() as it conflicts with the
327
// max() macro on Windows.
329
for (size_t i = 0; i <= max_count; ++i) {
330
// We know that the atom matches each of the first i characters in str.
331
if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
332
// We have enough matches at the head, and the tail matches too.
333
// Since we only care about *whether* the pattern matches str
334
// (as opposed to *how* it matches), there is no need to find a
338
if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
344
// Returns true iff regex matches a prefix of str. regex must be a
345
// valid simple regular expression and not start with "^", or the
346
// result is undefined.
347
bool MatchRegexAtHead(const char* regex, const char* str) {
348
if (*regex == '\0') // An empty regex matches a prefix of anything.
351
// "$" only matches the end of a string. Note that regex being
352
// valid guarantees that there's nothing after "$" in it.
356
// Is the first thing in regex an escape sequence?
357
const bool escaped = *regex == '\\';
360
if (IsRepeat(regex[1])) {
361
// MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
362
// here's an indirect recursion. It terminates as the regex gets
363
// shorter in each recursion.
364
return MatchRepetitionAndRegexAtHead(
365
escaped, regex[0], regex[1], regex + 2, str);
367
// regex isn't empty, isn't "$", and doesn't start with a
368
// repetition. We match the first atom of regex with the first
369
// character of str and recurse.
370
return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
371
MatchRegexAtHead(regex + 1, str + 1);
375
// Returns true iff regex matches any substring of str. regex must be
376
// a valid simple regular expression, or the result is undefined.
378
// The algorithm is recursive, but the recursion depth doesn't exceed
379
// the regex length, so we won't need to worry about running out of
380
// stack space normally. In rare cases the time complexity can be
381
// exponential with respect to the regex length + the string length,
382
// but usually it's must faster (often close to linear).
383
bool MatchRegexAnywhere(const char* regex, const char* str) {
384
if (regex == NULL || str == NULL)
388
return MatchRegexAtHead(regex + 1, str);
390
// A successful match can be anywhere in str.
392
if (MatchRegexAtHead(regex, str))
394
} while (*str++ != '\0');
398
// Implements the RE class.
401
free(const_cast<char*>(pattern_));
402
free(const_cast<char*>(full_pattern_));
405
// Returns true iff regular expression re matches the entire str.
406
bool RE::FullMatch(const char* str, const RE& re) {
407
return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
410
// Returns true iff regular expression re matches a substring of str
411
// (including str itself).
412
bool RE::PartialMatch(const char* str, const RE& re) {
413
return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
416
// Initializes an RE from its string representation.
417
void RE::Init(const char* regex) {
418
pattern_ = full_pattern_ = NULL;
420
pattern_ = posix::StrDup(regex);
423
is_valid_ = ValidateRegex(regex);
425
// No need to calculate the full pattern when the regex is invalid.
429
const size_t len = strlen(regex);
430
// Reserves enough bytes to hold the regular expression used for a
431
// full match: we need space to prepend a '^', append a '$', and
432
// terminate the string with '\0'.
433
char* buffer = static_cast<char*>(malloc(len + 3));
434
full_pattern_ = buffer;
437
*buffer++ = '^'; // Makes sure full_pattern_ starts with '^'.
439
// We don't use snprintf or strncpy, as they trigger a warning when
440
// compiled with VC++ 8.0.
441
memcpy(buffer, regex, len);
444
if (len == 0 || regex[len - 1] != '$')
445
*buffer++ = '$'; // Makes sure full_pattern_ ends with '$'.
450
#endif // GTEST_USES_POSIX_RE
452
const char kUnknownFile[] = "unknown file";
454
// Formats a source file path and a line number as they would appear
455
// in an error message from the compiler used to compile this code.
456
GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
457
const std::string file_name(file == NULL ? kUnknownFile : file);
460
return file_name + ":";
463
return file_name + "(" + StreamableToString(line) + "):";
465
return file_name + ":" + StreamableToString(line) + ":";
469
// Formats a file location for compiler-independent XML output.
470
// Although this function is not platform dependent, we put it next to
471
// FormatFileLocation in order to contrast the two functions.
472
// Note that FormatCompilerIndependentFileLocation() does NOT append colon
473
// to the file location it produces, unlike FormatFileLocation().
474
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
475
const char* file, int line) {
476
const std::string file_name(file == NULL ? kUnknownFile : file);
481
return file_name + ":" + StreamableToString(line);
485
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
486
: severity_(severity) {
487
const char* const marker =
488
severity == GTEST_INFO ? "[ INFO ]" :
489
severity == GTEST_WARNING ? "[WARNING]" :
490
severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
491
GetStream() << ::std::endl << marker << " "
492
<< FormatFileLocation(file, line).c_str() << ": ";
495
// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
496
GTestLog::~GTestLog() {
497
GetStream() << ::std::endl;
498
if (severity_ == GTEST_FATAL) {
503
// Disable Microsoft deprecation warnings for POSIX functions called from
504
// this class (creat, dup, dup2, and close)
506
# pragma warning(push)
507
# pragma warning(disable: 4996)
510
#if GTEST_HAS_STREAM_REDIRECTION
512
// Object that captures an output stream (stdout/stderr).
513
class CapturedStream {
515
// The ctor redirects the stream to a temporary file.
516
explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
517
# if GTEST_OS_WINDOWS
518
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
519
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
521
::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
522
const UINT success = ::GetTempFileNameA(temp_dir_path,
524
0, // Generate unique file name.
526
GTEST_CHECK_(success != 0)
527
<< "Unable to create a temporary file in " << temp_dir_path;
528
const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
529
GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
531
filename_ = temp_file_path;
533
// There's no guarantee that a test has write access to the current
534
// directory, so we create the temporary file in the /tmp directory
535
// instead. We use /tmp on most systems, and /sdcard on Android.
536
// That's because Android doesn't have /tmp.
537
# if GTEST_OS_LINUX_ANDROID
538
// Note: Android applications are expected to call the framework's
539
// Context.getExternalStorageDirectory() method through JNI to get
540
// the location of the world-writable SD Card directory. However,
541
// this requires a Context handle, which cannot be retrieved
542
// globally from native code. Doing so also precludes running the
543
// code as part of a regular standalone executable, which doesn't
544
// run in a Dalvik process (e.g. when running it through 'adb shell').
546
// The location /sdcard is directly accessible from native code
547
// and is the only location (unofficially) supported by the Android
548
// team. It's generally a symlink to the real SD Card mount point
549
// which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
550
// other OEM-customized locations. Never rely on these, and always
552
char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
554
char name_template[] = "/tmp/captured_stream.XXXXXX";
555
# endif // GTEST_OS_LINUX_ANDROID
556
const int captured_fd = mkstemp(name_template);
557
filename_ = name_template;
558
# endif // GTEST_OS_WINDOWS
560
dup2(captured_fd, fd_);
565
remove(filename_.c_str());
568
std::string GetCapturedString() {
569
if (uncaptured_fd_ != -1) {
570
// Restores the original stream.
572
dup2(uncaptured_fd_, fd_);
573
close(uncaptured_fd_);
577
FILE* const file = posix::FOpen(filename_.c_str(), "r");
578
const std::string content = ReadEntireFile(file);
584
// Reads the entire content of a file as an std::string.
585
static std::string ReadEntireFile(FILE* file);
587
// Returns the size (in bytes) of a file.
588
static size_t GetFileSize(FILE* file);
590
const int fd_; // A stream to capture.
592
// Name of the temporary file holding the stderr output.
593
::std::string filename_;
595
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
598
// Returns the size (in bytes) of a file.
599
size_t CapturedStream::GetFileSize(FILE* file) {
600
fseek(file, 0, SEEK_END);
601
return static_cast<size_t>(ftell(file));
604
// Reads the entire content of a file as a string.
605
std::string CapturedStream::ReadEntireFile(FILE* file) {
606
const size_t file_size = GetFileSize(file);
607
char* const buffer = new char[file_size];
609
size_t bytes_last_read = 0; // # of bytes read in the last fread()
610
size_t bytes_read = 0; // # of bytes read so far
612
fseek(file, 0, SEEK_SET);
614
// Keeps reading the file until we cannot read further or the
615
// pre-determined file size is reached.
617
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
618
bytes_read += bytes_last_read;
619
} while (bytes_last_read > 0 && bytes_read < file_size);
621
const std::string content(buffer, bytes_read);
628
# pragma warning(pop)
631
static CapturedStream* g_captured_stderr = NULL;
632
static CapturedStream* g_captured_stdout = NULL;
634
// Starts capturing an output stream (stdout/stderr).
635
void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
636
if (*stream != NULL) {
637
GTEST_LOG_(FATAL) << "Only one " << stream_name
638
<< " capturer can exist at a time.";
640
*stream = new CapturedStream(fd);
643
// Stops capturing the output stream and returns the captured string.
644
std::string GetCapturedStream(CapturedStream** captured_stream) {
645
const std::string content = (*captured_stream)->GetCapturedString();
647
delete *captured_stream;
648
*captured_stream = NULL;
653
// Starts capturing stdout.
654
void CaptureStdout() {
655
CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
658
// Starts capturing stderr.
659
void CaptureStderr() {
660
CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
663
// Stops capturing stdout and returns the captured string.
664
std::string GetCapturedStdout() {
665
return GetCapturedStream(&g_captured_stdout);
668
// Stops capturing stderr and returns the captured string.
669
std::string GetCapturedStderr() {
670
return GetCapturedStream(&g_captured_stderr);
673
#endif // GTEST_HAS_STREAM_REDIRECTION
675
#if GTEST_HAS_DEATH_TEST
677
// A copy of all command line arguments. Set by InitGoogleTest().
678
::std::vector<testing::internal::string> g_argvs;
680
static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
683
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
684
if (g_injected_test_argvs != argvs)
685
delete g_injected_test_argvs;
686
g_injected_test_argvs = argvs;
689
const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
690
if (g_injected_test_argvs != NULL) {
691
return *g_injected_test_argvs;
695
#endif // GTEST_HAS_DEATH_TEST
697
#if GTEST_OS_WINDOWS_MOBILE
701
TerminateProcess(GetCurrentProcess(), 1);
704
#endif // GTEST_OS_WINDOWS_MOBILE
706
// Returns the name of the environment variable corresponding to the
707
// given flag. For example, FlagToEnvVar("foo") will return
708
// "GTEST_FOO" in the open-source version.
709
static std::string FlagToEnvVar(const char* flag) {
710
const std::string full_flag =
711
(Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
714
for (size_t i = 0; i != full_flag.length(); i++) {
715
env_var << ToUpper(full_flag.c_str()[i]);
718
return env_var.GetString();
721
// Parses 'str' for a 32-bit signed integer. If successful, writes
722
// the result to *value and returns true; otherwise leaves *value
723
// unchanged and returns false.
724
bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
725
// Parses the environment variable as a decimal integer.
727
const long long_value = strtol(str, &end, 10); // NOLINT
729
// Has strtol() consumed all characters in the string?
731
// No - an invalid character was encountered.
733
msg << "WARNING: " << src_text
734
<< " is expected to be a 32-bit integer, but actually"
735
<< " has value \"" << str << "\".\n";
736
printf("%s", msg.GetString().c_str());
741
// Is the parsed value in the range of an Int32?
742
const Int32 result = static_cast<Int32>(long_value);
743
if (long_value == LONG_MAX || long_value == LONG_MIN ||
744
// The parsed value overflows as a long. (strtol() returns
745
// LONG_MAX or LONG_MIN when the input overflows.)
747
// The parsed value overflows as an Int32.
750
msg << "WARNING: " << src_text
751
<< " is expected to be a 32-bit integer, but actually"
752
<< " has value " << str << ", which overflows.\n";
753
printf("%s", msg.GetString().c_str());
762
// Reads and returns the Boolean environment variable corresponding to
763
// the given flag; if it's not set, returns default_value.
765
// The value is considered true iff it's not "0".
766
bool BoolFromGTestEnv(const char* flag, bool default_value) {
767
const std::string env_var = FlagToEnvVar(flag);
768
const char* const string_value = posix::GetEnv(env_var.c_str());
769
return string_value == NULL ?
770
default_value : strcmp(string_value, "0") != 0;
773
// Reads and returns a 32-bit integer stored in the environment
774
// variable corresponding to the given flag; if it isn't set or
775
// doesn't represent a valid 32-bit integer, returns default_value.
776
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
777
const std::string env_var = FlagToEnvVar(flag);
778
const char* const string_value = posix::GetEnv(env_var.c_str());
779
if (string_value == NULL) {
780
// The environment variable is not set.
781
return default_value;
784
Int32 result = default_value;
785
if (!ParseInt32(Message() << "Environment variable " << env_var,
786
string_value, &result)) {
787
printf("The default value %s is used.\n",
788
(Message() << default_value).GetString().c_str());
790
return default_value;
796
// Reads and returns the string environment variable corresponding to
797
// the given flag; if it's not set, returns default_value.
798
const char* StringFromGTestEnv(const char* flag, const char* default_value) {
799
const std::string env_var = FlagToEnvVar(flag);
800
const char* const value = posix::GetEnv(env_var.c_str());
801
return value == NULL ? default_value : value;
804
} // namespace internal
805
} // namespace testing