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