00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "gtest/internal/gtest-port.h"
00033
00034 #include <limits.h>
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <string.h>
00038
00039 #if GTEST_OS_WINDOWS_MOBILE
00040 # include <windows.h>
00041 #elif GTEST_OS_WINDOWS
00042 # include <io.h>
00043 # include <sys/stat.h>
00044 #else
00045 # include <unistd.h>
00046 #endif // GTEST_OS_WINDOWS_MOBILE
00047
00048 #if GTEST_OS_MAC
00049 # include <mach/mach_init.h>
00050 # include <mach/task.h>
00051 # include <mach/vm_map.h>
00052 #endif // GTEST_OS_MAC
00053
00054 #if GTEST_OS_QNX
00055 # include <devctl.h>
00056 # include <sys/procfs.h>
00057 #endif // GTEST_OS_QNX
00058
00059 #include "gtest/gtest-spi.h"
00060 #include "gtest/gtest-message.h"
00061 #include "gtest/internal/gtest-internal.h"
00062 #include "gtest/internal/gtest-string.h"
00063
00064
00065
00066
00067
00068
00069 #define GTEST_IMPLEMENTATION_ 1
00070 #include "src/gtest-internal-inl.h"
00071 #undef GTEST_IMPLEMENTATION_
00072
00073 namespace testing {
00074 namespace internal {
00075
00076 #if defined(_MSC_VER) || defined(__BORLANDC__)
00077
00078 const int kStdOutFileno = 1;
00079 const int kStdErrFileno = 2;
00080 #else
00081 const int kStdOutFileno = STDOUT_FILENO;
00082 const int kStdErrFileno = STDERR_FILENO;
00083 #endif // _MSC_VER
00084
00085 #if GTEST_OS_MAC
00086
00087
00088
00089 size_t GetThreadCount() {
00090 const task_t task = mach_task_self();
00091 mach_msg_type_number_t thread_count;
00092 thread_act_array_t thread_list;
00093 const kern_return_t status = task_threads(task, &thread_list, &thread_count);
00094 if (status == KERN_SUCCESS) {
00095
00096
00097 vm_deallocate(task,
00098 reinterpret_cast<vm_address_t>(thread_list),
00099 sizeof(thread_t) * thread_count);
00100 return static_cast<size_t>(thread_count);
00101 } else {
00102 return 0;
00103 }
00104 }
00105
00106 #elif GTEST_OS_QNX
00107
00108
00109
00110 size_t GetThreadCount() {
00111 const int fd = open("/proc/self/as", O_RDONLY);
00112 if (fd < 0) {
00113 return 0;
00114 }
00115 procfs_info process_info;
00116 const int status =
00117 devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
00118 close(fd);
00119 if (status == EOK) {
00120 return static_cast<size_t>(process_info.num_threads);
00121 } else {
00122 return 0;
00123 }
00124 }
00125
00126 #else
00127
00128 size_t GetThreadCount() {
00129
00130
00131 return 0;
00132 }
00133
00134 #endif // GTEST_OS_MAC
00135
00136 #if GTEST_USES_POSIX_RE
00137
00138
00139
00140 RE::~RE() {
00141 if (is_valid_) {
00142
00143
00144
00145
00146 regfree(&partial_regex_);
00147 regfree(&full_regex_);
00148 }
00149 free(const_cast<char*>(pattern_));
00150 }
00151
00152
00153 bool RE::FullMatch(const char* str, const RE& re) {
00154 if (!re.is_valid_) return false;
00155
00156 regmatch_t match;
00157 return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
00158 }
00159
00160
00161
00162 bool RE::PartialMatch(const char* str, const RE& re) {
00163 if (!re.is_valid_) return false;
00164
00165 regmatch_t match;
00166 return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
00167 }
00168
00169
00170 void RE::Init(const char* regex) {
00171 pattern_ = posix::StrDup(regex);
00172
00173
00174
00175 const size_t full_regex_len = strlen(regex) + 10;
00176 char* const full_pattern = new char[full_regex_len];
00177
00178 snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
00179 is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
00180
00181
00182
00183
00184
00185
00186
00187
00188 if (is_valid_) {
00189 const char* const partial_regex = (*regex == '\0') ? "()" : regex;
00190 is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
00191 }
00192 EXPECT_TRUE(is_valid_)
00193 << "Regular expression \"" << regex
00194 << "\" is not a valid POSIX Extended regular expression.";
00195
00196 delete[] full_pattern;
00197 }
00198
00199 #elif GTEST_USES_SIMPLE_RE
00200
00201
00202
00203 bool IsInSet(char ch, const char* str) {
00204 return ch != '\0' && strchr(str, ch) != NULL;
00205 }
00206
00207
00208
00209
00210 bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
00211 bool IsAsciiPunct(char ch) {
00212 return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
00213 }
00214 bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
00215 bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
00216 bool IsAsciiWordChar(char ch) {
00217 return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
00218 ('0' <= ch && ch <= '9') || ch == '_';
00219 }
00220
00221
00222 bool IsValidEscape(char c) {
00223 return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
00224 }
00225
00226
00227
00228 bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
00229 if (escaped) {
00230 switch (pattern_char) {
00231 case 'd': return IsAsciiDigit(ch);
00232 case 'D': return !IsAsciiDigit(ch);
00233 case 'f': return ch == '\f';
00234 case 'n': return ch == '\n';
00235 case 'r': return ch == '\r';
00236 case 's': return IsAsciiWhiteSpace(ch);
00237 case 'S': return !IsAsciiWhiteSpace(ch);
00238 case 't': return ch == '\t';
00239 case 'v': return ch == '\v';
00240 case 'w': return IsAsciiWordChar(ch);
00241 case 'W': return !IsAsciiWordChar(ch);
00242 }
00243 return IsAsciiPunct(pattern_char) && pattern_char == ch;
00244 }
00245
00246 return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
00247 }
00248
00249
00250 std::string FormatRegexSyntaxError(const char* regex, int index) {
00251 return (Message() << "Syntax error at index " << index
00252 << " in simple regular expression \"" << regex << "\": ").GetString();
00253 }
00254
00255
00256
00257 bool ValidateRegex(const char* regex) {
00258 if (regex == NULL) {
00259
00260
00261
00262 ADD_FAILURE() << "NULL is not a valid simple regular expression.";
00263 return false;
00264 }
00265
00266 bool is_valid = true;
00267
00268
00269 bool prev_repeatable = false;
00270 for (int i = 0; regex[i]; i++) {
00271 if (regex[i] == '\\') {
00272 i++;
00273 if (regex[i] == '\0') {
00274 ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
00275 << "'\\' cannot appear at the end.";
00276 return false;
00277 }
00278
00279 if (!IsValidEscape(regex[i])) {
00280 ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
00281 << "invalid escape sequence \"\\" << regex[i] << "\".";
00282 is_valid = false;
00283 }
00284 prev_repeatable = true;
00285 } else {
00286 const char ch = regex[i];
00287
00288 if (ch == '^' && i > 0) {
00289 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
00290 << "'^' can only appear at the beginning.";
00291 is_valid = false;
00292 } else if (ch == '$' && regex[i + 1] != '\0') {
00293 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
00294 << "'$' can only appear at the end.";
00295 is_valid = false;
00296 } else if (IsInSet(ch, "()[]{}|")) {
00297 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
00298 << "'" << ch << "' is unsupported.";
00299 is_valid = false;
00300 } else if (IsRepeat(ch) && !prev_repeatable) {
00301 ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
00302 << "'" << ch << "' can only follow a repeatable token.";
00303 is_valid = false;
00304 }
00305
00306 prev_repeatable = !IsInSet(ch, "^$?*+");
00307 }
00308 }
00309
00310 return is_valid;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320 bool MatchRepetitionAndRegexAtHead(
00321 bool escaped, char c, char repeat, const char* regex,
00322 const char* str) {
00323 const size_t min_count = (repeat == '+') ? 1 : 0;
00324 const size_t max_count = (repeat == '?') ? 1 :
00325 static_cast<size_t>(-1) - 1;
00326
00327
00328
00329 for (size_t i = 0; i <= max_count; ++i) {
00330
00331 if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
00332
00333
00334
00335
00336 return true;
00337 }
00338 if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
00339 return false;
00340 }
00341 return false;
00342 }
00343
00344
00345
00346
00347 bool MatchRegexAtHead(const char* regex, const char* str) {
00348 if (*regex == '\0')
00349 return true;
00350
00351
00352
00353 if (*regex == '$')
00354 return *str == '\0';
00355
00356
00357 const bool escaped = *regex == '\\';
00358 if (escaped)
00359 ++regex;
00360 if (IsRepeat(regex[1])) {
00361
00362
00363
00364 return MatchRepetitionAndRegexAtHead(
00365 escaped, regex[0], regex[1], regex + 2, str);
00366 } else {
00367
00368
00369
00370 return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
00371 MatchRegexAtHead(regex + 1, str + 1);
00372 }
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 bool MatchRegexAnywhere(const char* regex, const char* str) {
00384 if (regex == NULL || str == NULL)
00385 return false;
00386
00387 if (*regex == '^')
00388 return MatchRegexAtHead(regex + 1, str);
00389
00390
00391 do {
00392 if (MatchRegexAtHead(regex, str))
00393 return true;
00394 } while (*str++ != '\0');
00395 return false;
00396 }
00397
00398
00399
00400 RE::~RE() {
00401 free(const_cast<char*>(pattern_));
00402 free(const_cast<char*>(full_pattern_));
00403 }
00404
00405
00406 bool RE::FullMatch(const char* str, const RE& re) {
00407 return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
00408 }
00409
00410
00411
00412 bool RE::PartialMatch(const char* str, const RE& re) {
00413 return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
00414 }
00415
00416
00417 void RE::Init(const char* regex) {
00418 pattern_ = full_pattern_ = NULL;
00419 if (regex != NULL) {
00420 pattern_ = posix::StrDup(regex);
00421 }
00422
00423 is_valid_ = ValidateRegex(regex);
00424 if (!is_valid_) {
00425
00426 return;
00427 }
00428
00429 const size_t len = strlen(regex);
00430
00431
00432
00433 char* buffer = static_cast<char*>(malloc(len + 3));
00434 full_pattern_ = buffer;
00435
00436 if (*regex != '^')
00437 *buffer++ = '^';
00438
00439
00440
00441 memcpy(buffer, regex, len);
00442 buffer += len;
00443
00444 if (len == 0 || regex[len - 1] != '$')
00445 *buffer++ = '$';
00446
00447 *buffer = '\0';
00448 }
00449
00450 #endif // GTEST_USES_POSIX_RE
00451
00452 const char kUnknownFile[] = "unknown file";
00453
00454
00455
00456 GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
00457 const std::string file_name(file == NULL ? kUnknownFile : file);
00458
00459 if (line < 0) {
00460 return file_name + ":";
00461 }
00462 #ifdef _MSC_VER
00463 return file_name + "(" + StreamableToString(line) + "):";
00464 #else
00465 return file_name + ":" + StreamableToString(line) + ":";
00466 #endif // _MSC_VER
00467 }
00468
00469
00470
00471
00472
00473
00474 GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
00475 const char* file, int line) {
00476 const std::string file_name(file == NULL ? kUnknownFile : file);
00477
00478 if (line < 0)
00479 return file_name;
00480 else
00481 return file_name + ":" + StreamableToString(line);
00482 }
00483
00484
00485 GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
00486 : severity_(severity) {
00487 const char* const marker =
00488 severity == GTEST_INFO ? "[ INFO ]" :
00489 severity == GTEST_WARNING ? "[WARNING]" :
00490 severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
00491 GetStream() << ::std::endl << marker << " "
00492 << FormatFileLocation(file, line).c_str() << ": ";
00493 }
00494
00495
00496 GTestLog::~GTestLog() {
00497 GetStream() << ::std::endl;
00498 if (severity_ == GTEST_FATAL) {
00499 fflush(stderr);
00500 posix::Abort();
00501 }
00502 }
00503
00504
00505 #ifdef _MSC_VER
00506 # pragma warning(push)
00507 # pragma warning(disable: 4996)
00508 #endif // _MSC_VER
00509
00510 #if GTEST_HAS_STREAM_REDIRECTION
00511
00512
00513 class CapturedStream {
00514 public:
00515
00516 explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
00517 # if GTEST_OS_WINDOWS
00518 char temp_dir_path[MAX_PATH + 1] = { '\0' };
00519 char temp_file_path[MAX_PATH + 1] = { '\0' };
00520
00521 ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
00522 const UINT success = ::GetTempFileNameA(temp_dir_path,
00523 "gtest_redir",
00524 0,
00525 temp_file_path);
00526 GTEST_CHECK_(success != 0)
00527 << "Unable to create a temporary file in " << temp_dir_path;
00528 const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
00529 GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
00530 << temp_file_path;
00531 filename_ = temp_file_path;
00532 # else
00533
00534
00535
00536
00537 # if GTEST_OS_LINUX_ANDROID
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
00553 # else
00554 char name_template[] = "/tmp/captured_stream.XXXXXX";
00555 # endif // GTEST_OS_LINUX_ANDROID
00556 const int captured_fd = mkstemp(name_template);
00557 filename_ = name_template;
00558 # endif // GTEST_OS_WINDOWS
00559 fflush(NULL);
00560 dup2(captured_fd, fd_);
00561 close(captured_fd);
00562 }
00563
00564 ~CapturedStream() {
00565 remove(filename_.c_str());
00566 }
00567
00568 std::string GetCapturedString() {
00569 if (uncaptured_fd_ != -1) {
00570
00571 fflush(NULL);
00572 dup2(uncaptured_fd_, fd_);
00573 close(uncaptured_fd_);
00574 uncaptured_fd_ = -1;
00575 }
00576
00577 FILE* const file = posix::FOpen(filename_.c_str(), "r");
00578 const std::string content = ReadEntireFile(file);
00579 posix::FClose(file);
00580 return content;
00581 }
00582
00583 private:
00584
00585 static std::string ReadEntireFile(FILE* file);
00586
00587
00588 static size_t GetFileSize(FILE* file);
00589
00590 const int fd_;
00591 int uncaptured_fd_;
00592
00593 ::std::string filename_;
00594
00595 GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
00596 };
00597
00598
00599 size_t CapturedStream::GetFileSize(FILE* file) {
00600 fseek(file, 0, SEEK_END);
00601 return static_cast<size_t>(ftell(file));
00602 }
00603
00604
00605 std::string CapturedStream::ReadEntireFile(FILE* file) {
00606 const size_t file_size = GetFileSize(file);
00607 char* const buffer = new char[file_size];
00608
00609 size_t bytes_last_read = 0;
00610 size_t bytes_read = 0;
00611
00612 fseek(file, 0, SEEK_SET);
00613
00614
00615
00616 do {
00617 bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
00618 bytes_read += bytes_last_read;
00619 } while (bytes_last_read > 0 && bytes_read < file_size);
00620
00621 const std::string content(buffer, bytes_read);
00622 delete[] buffer;
00623
00624 return content;
00625 }
00626
00627 # ifdef _MSC_VER
00628 # pragma warning(pop)
00629 # endif // _MSC_VER
00630
00631 static CapturedStream* g_captured_stderr = NULL;
00632 static CapturedStream* g_captured_stdout = NULL;
00633
00634
00635 void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
00636 if (*stream != NULL) {
00637 GTEST_LOG_(FATAL) << "Only one " << stream_name
00638 << " capturer can exist at a time.";
00639 }
00640 *stream = new CapturedStream(fd);
00641 }
00642
00643
00644 std::string GetCapturedStream(CapturedStream** captured_stream) {
00645 const std::string content = (*captured_stream)->GetCapturedString();
00646
00647 delete *captured_stream;
00648 *captured_stream = NULL;
00649
00650 return content;
00651 }
00652
00653
00654 void CaptureStdout() {
00655 CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
00656 }
00657
00658
00659 void CaptureStderr() {
00660 CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
00661 }
00662
00663
00664 std::string GetCapturedStdout() {
00665 return GetCapturedStream(&g_captured_stdout);
00666 }
00667
00668
00669 std::string GetCapturedStderr() {
00670 return GetCapturedStream(&g_captured_stderr);
00671 }
00672
00673 #endif // GTEST_HAS_STREAM_REDIRECTION
00674
00675 #if GTEST_HAS_DEATH_TEST
00676
00677
00678 ::std::vector<testing::internal::string> g_argvs;
00679
00680 static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
00681 NULL;
00682
00683 void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
00684 if (g_injected_test_argvs != argvs)
00685 delete g_injected_test_argvs;
00686 g_injected_test_argvs = argvs;
00687 }
00688
00689 const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
00690 if (g_injected_test_argvs != NULL) {
00691 return *g_injected_test_argvs;
00692 }
00693 return g_argvs;
00694 }
00695 #endif // GTEST_HAS_DEATH_TEST
00696
00697 #if GTEST_OS_WINDOWS_MOBILE
00698 namespace posix {
00699 void Abort() {
00700 DebugBreak();
00701 TerminateProcess(GetCurrentProcess(), 1);
00702 }
00703 }
00704 #endif // GTEST_OS_WINDOWS_MOBILE
00705
00706
00707
00708
00709 static std::string FlagToEnvVar(const char* flag) {
00710 const std::string full_flag =
00711 (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
00712
00713 Message env_var;
00714 for (size_t i = 0; i != full_flag.length(); i++) {
00715 env_var << ToUpper(full_flag.c_str()[i]);
00716 }
00717
00718 return env_var.GetString();
00719 }
00720
00721
00722
00723
00724 bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
00725
00726 char* end = NULL;
00727 const long long_value = strtol(str, &end, 10);
00728
00729
00730 if (*end != '\0') {
00731
00732 Message msg;
00733 msg << "WARNING: " << src_text
00734 << " is expected to be a 32-bit integer, but actually"
00735 << " has value \"" << str << "\".\n";
00736 printf("%s", msg.GetString().c_str());
00737 fflush(stdout);
00738 return false;
00739 }
00740
00741
00742 const Int32 result = static_cast<Int32>(long_value);
00743 if (long_value == LONG_MAX || long_value == LONG_MIN ||
00744
00745
00746 result != long_value
00747
00748 ) {
00749 Message msg;
00750 msg << "WARNING: " << src_text
00751 << " is expected to be a 32-bit integer, but actually"
00752 << " has value " << str << ", which overflows.\n";
00753 printf("%s", msg.GetString().c_str());
00754 fflush(stdout);
00755 return false;
00756 }
00757
00758 *value = result;
00759 return true;
00760 }
00761
00762
00763
00764
00765
00766 bool BoolFromGTestEnv(const char* flag, bool default_value) {
00767 const std::string env_var = FlagToEnvVar(flag);
00768 const char* const string_value = posix::GetEnv(env_var.c_str());
00769 return string_value == NULL ?
00770 default_value : strcmp(string_value, "0") != 0;
00771 }
00772
00773
00774
00775
00776 Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
00777 const std::string env_var = FlagToEnvVar(flag);
00778 const char* const string_value = posix::GetEnv(env_var.c_str());
00779 if (string_value == NULL) {
00780
00781 return default_value;
00782 }
00783
00784 Int32 result = default_value;
00785 if (!ParseInt32(Message() << "Environment variable " << env_var,
00786 string_value, &result)) {
00787 printf("The default value %s is used.\n",
00788 (Message() << default_value).GetString().c_str());
00789 fflush(stdout);
00790 return default_value;
00791 }
00792
00793 return result;
00794 }
00795
00796
00797
00798 const char* StringFromGTestEnv(const char* flag, const char* default_value) {
00799 const std::string env_var = FlagToEnvVar(flag);
00800 const char* const value = posix::GetEnv(env_var.c_str());
00801 return value == NULL ? default_value : value;
00802 }
00803
00804 }
00805 }