aboutsummaryrefslogtreecommitdiff
path: root/utils/unittest/googletest/gtest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'utils/unittest/googletest/gtest.cc')
-rw-r--r--utils/unittest/googletest/gtest.cc1729
1 files changed, 1025 insertions, 704 deletions
diff --git a/utils/unittest/googletest/gtest.cc b/utils/unittest/googletest/gtest.cc
index 8f4252dad4..8657a8aa02 100644
--- a/utils/unittest/googletest/gtest.cc
+++ b/utils/unittest/googletest/gtest.cc
@@ -39,10 +39,11 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <wchar.h>
#include <wctype.h>
+#include <ostream>
+
#if GTEST_OS_LINUX
// TODO(kenton@google.com): Use autoconf to detect availability of
@@ -71,7 +72,7 @@
// On z/OS we additionally need strings.h for strcasecmp.
#include <strings.h> // NOLINT
-#elif defined(_WIN32_WCE) // We are on Windows CE.
+#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
#include <windows.h> // NOLINT
@@ -82,7 +83,7 @@
#include <sys/types.h> // NOLINT
#include <sys/stat.h> // NOLINT
-#if defined(__MINGW__) || defined(__MINGW32__)
+#if GTEST_OS_WINDOWS_MINGW
// MinGW has gettimeofday() but not _ftime64().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
@@ -91,7 +92,7 @@
// supports these. consider using them instead.
#define GTEST_HAS_GETTIMEOFDAY_ 1
#include <sys/time.h> // NOLINT
-#endif // defined(__MINGW__) || defined(__MINGW32__)
+#endif // GTEST_OS_WINDOWS_MINGW
// cpplint thinks that the header is already included, so we want to
// silence it.
@@ -125,8 +126,6 @@
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_WINDOWS
-#define fileno _fileno
-#define isatty _isatty
#define vsnprintf _vsnprintf
#endif // GTEST_OS_WINDOWS
@@ -186,7 +185,7 @@ GTEST_DEFINE_string_(
"Whether to use colors in the output. Valid values: yes, no, "
"and auto. 'auto' means to use colors if the output is "
"being sent to a terminal and the TERM environment variable "
- "is set to xterm or xterm-color.");
+ "is set to xterm, xterm-color, xterm-256color, linux or cygwin.");
GTEST_DEFINE_string_(
filter,
@@ -214,16 +213,33 @@ GTEST_DEFINE_string_(
GTEST_DEFINE_bool_(
print_time,
- internal::BoolFromGTestEnv("print_time", false),
+ internal::BoolFromGTestEnv("print_time", true),
"True iff " GTEST_NAME_
" should display elapsed time in text output.");
GTEST_DEFINE_int32_(
+ random_seed,
+ internal::Int32FromGTestEnv("random_seed", 0),
+ "Random number seed to use when shuffling test orders. Must be in range "
+ "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
repeat,
internal::Int32FromGTestEnv("repeat", 1),
"How many times to repeat each test. Specify a negative number "
"for repeating forever. Useful for shaking out flaky tests.");
+GTEST_DEFINE_bool_(
+ show_internal_stack_frames, false,
+ "True iff " GTEST_NAME_ " should include internal stack frames when "
+ "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+ shuffle,
+ internal::BoolFromGTestEnv("shuffle", false),
+ "True iff " GTEST_NAME_
+ " should randomize tests' order on every run.");
+
GTEST_DEFINE_int32_(
stack_trace_depth,
internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
@@ -231,11 +247,6 @@ GTEST_DEFINE_int32_(
"assertion fails. The valid range is 0 through 100, inclusive.");
GTEST_DEFINE_bool_(
- show_internal_stack_frames, false,
- "True iff " GTEST_NAME_ " should include internal stack frames when "
- "printing test failure stack traces.");
-
-GTEST_DEFINE_bool_(
throw_on_failure,
internal::BoolFromGTestEnv("throw_on_failure", false),
"When this flag is specified, a failed assertion will throw an exception "
@@ -244,6 +255,25 @@ GTEST_DEFINE_bool_(
namespace internal {
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG). Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+ // These constants are the same as are used in glibc's rand(3).
+ state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+ GTEST_CHECK_(range > 0)
+ << "Cannot generate a number in the range [0, 0).";
+ GTEST_CHECK_(range <= kMaxRange)
+ << "Generation of a number in [0, " << range << ") was requested, "
+ << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+ // Converting via modulus introduces a bit of downward bias, but
+ // it's simple, and a linear congruential generator isn't too good
+ // to begin with.
+ return state_ % range;
+}
+
// g_help_flag is true iff the --help flag or an equivalent form is
// specified on the command line.
static bool g_help_flag = false;
@@ -259,16 +289,14 @@ static bool g_help_flag = false;
int g_init_gtest_count = 0;
static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
-// Iterates over a list of TestCases, keeping a running sum of the
+// Iterates over a vector of TestCases, keeping a running sum of the
// results of calling a given int-returning method on each.
// Returns the sum.
-static int SumOverTestCaseList(const internal::List<TestCase*>& case_list,
+static int SumOverTestCaseList(const internal::Vector<TestCase*>& case_list,
int (TestCase::*method)() const) {
int sum = 0;
- for (const internal::ListNode<TestCase*>* node = case_list.Head();
- node != NULL;
- node = node->next()) {
- sum += (node->element()->*method)();
+ for (int i = 0; i < case_list.size(); i++) {
+ sum += (case_list.GetElement(i)->*method)();
}
return sum;
}
@@ -290,16 +318,22 @@ static bool ShouldRunTestCase(const TestCase* test_case) {
}
// AssertHelper constructor.
-AssertHelper::AssertHelper(TestPartResultType type, const char* file,
- int line, const char* message)
- : type_(type), file_(file), line_(line), message_(message) {
+AssertHelper::AssertHelper(TestPartResult::Type type,
+ const char* file,
+ int line,
+ const char* message)
+ : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+ delete data_;
}
// Message assignment, for assertion streaming support.
void AssertHelper::operator=(const Message& message) const {
UnitTest::GetInstance()->
- AddTestPartResult(type_, file_, line_,
- AppendUserMessage(message_, message),
+ AddTestPartResult(data_->type, data_->file, data_->line,
+ AppendUserMessage(data_->message, message),
UnitTest::GetInstance()->impl()
->CurrentOsStackTraceExceptTop(1)
// Skips the stack frame for this function itself.
@@ -317,11 +351,11 @@ String g_executable_path;
FilePath GetCurrentExecutableName() {
FilePath result;
-#if defined(_WIN32_WCE) || GTEST_OS_WINDOWS
+#if GTEST_OS_WINDOWS
result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
#else
result.Set(FilePath(g_executable_path));
-#endif // _WIN32_WCE || GTEST_OS_WINDOWS
+#endif // GTEST_OS_WINDOWS
return result.RemoveDirectoryName();
}
@@ -434,7 +468,7 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter
negative = String("");
} else {
- positive.Set(p, dash - p); // Everything up to the dash
+ positive = String(p, dash - p); // Everything up to the dash
negative = String(dash+1); // Everything after the dash
if (positive.empty()) {
// Treat '-test1' as the same as '*-test1'
@@ -465,46 +499,6 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
} // namespace internal
-// The interface for printing the result of a UnitTest
-class UnitTestEventListenerInterface {
- public:
- // The d'tor is pure virtual as this is an abstract class.
- virtual ~UnitTestEventListenerInterface() = 0;
-
- // Called before the unit test starts.
- virtual void OnUnitTestStart(const UnitTest*) {}
-
- // Called after the unit test ends.
- virtual void OnUnitTestEnd(const UnitTest*) {}
-
- // Called before the test case starts.
- virtual void OnTestCaseStart(const TestCase*) {}
-
- // Called after the test case ends.
- virtual void OnTestCaseEnd(const TestCase*) {}
-
- // Called before the global set-up starts.
- virtual void OnGlobalSetUpStart(const UnitTest*) {}
-
- // Called after the global set-up ends.
- virtual void OnGlobalSetUpEnd(const UnitTest*) {}
-
- // Called before the global tear-down starts.
- virtual void OnGlobalTearDownStart(const UnitTest*) {}
-
- // Called after the global tear-down ends.
- virtual void OnGlobalTearDownEnd(const UnitTest*) {}
-
- // Called before the test starts.
- virtual void OnTestStart(const TestInfo*) {}
-
- // Called after the test ends.
- virtual void OnTestEnd(const TestInfo*) {}
-
- // Called after an assertion.
- virtual void OnNewTestPartResult(const TestPartResult*) {}
-};
-
// The c'tor sets this object as the test part result reporter used by
// Google Test. The 'result' parameter specifies where to report the
// results. Intercepts only failures from the current thread.
@@ -526,7 +520,7 @@ ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
}
void ScopedFakeTestPartResultReporter::Init() {
- internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl();
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
old_reporter_ = impl->GetGlobalTestPartResultReporter();
impl->SetGlobalTestPartResultReporter(this);
@@ -539,7 +533,7 @@ void ScopedFakeTestPartResultReporter::Init() {
// The d'tor restores the test part result reporter used by Google Test
// before.
ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
- internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl();
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
impl->SetGlobalTestPartResultReporter(old_reporter_);
} else {
@@ -580,11 +574,11 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
const char* /* type_expr */,
const char* /* substr_expr */,
const TestPartResultArray& results,
- TestPartResultType type,
+ TestPartResult::Type type,
const char* substr) {
- const String expected(
- type == TPRT_FATAL_FAILURE ? "1 fatal failure" :
- "1 non-fatal failure");
+ const String expected(type == TestPartResult::kFatalFailure ?
+ "1 fatal failure" :
+ "1 non-fatal failure");
Message msg;
if (results.size() != 1) {
msg << "Expected: " << expected << "\n"
@@ -619,7 +613,7 @@ AssertionResult HasOneFailure(const char* /* results_expr */,
// substring the failure message should contain.
SingleFailureChecker:: SingleFailureChecker(
const TestPartResultArray* results,
- TestPartResultType type,
+ TestPartResult::Type type,
const char* substr)
: results_(results),
type_(type),
@@ -639,7 +633,7 @@ DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
const TestPartResult& result) {
unit_test_->current_test_result()->AddTestPartResult(result);
- unit_test_->result_printer()->OnNewTestPartResult(&result);
+ unit_test_->listeners()->repeater()->OnTestPartResult(result);
}
DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
@@ -737,11 +731,13 @@ String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
return String("");
}
-static TimeInMillis GetTimeInMillis() {
-#ifdef _WIN32_WCE // We are on Windows CE
- // Difference between 1970-01-01 and 1601-01-01 in miliseconds.
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+ // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
// http://analogous.blogspot.com/2005/04/epoch.html
- const TimeInMillis kJavaEpochToWinFileTimeDelta = 11644473600000UL;
+ const TimeInMillis kJavaEpochToWinFileTimeDelta =
+ static_cast<TimeInMillis>(116444736UL) * 100000UL;
const DWORD kTenthMicrosInMilliSecond = 10000;
SYSTEMTIME now_systime;
@@ -806,16 +802,7 @@ static char* CloneString(const char* str, size_t length) {
return NULL;
} else {
char* const clone = new char[length + 1];
- // MSVC 8 deprecates strncpy(), so we want to suppress warning
- // 4996 (deprecated function) there.
-#if GTEST_OS_WINDOWS // We are on Windows.
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
- strncpy(clone, str, length);
-#pragma warning(pop) // Restores the warning state.
-#else // We are on Linux or Mac OS.
- strncpy(clone, str, length);
-#endif // GTEST_OS_WINDOWS
+ posix::StrNCpy(clone, str, length);
clone[length] = '\0';
return clone;
}
@@ -829,7 +816,7 @@ const char * String::CloneCString(const char* c_str) {
NULL : CloneString(c_str, strlen(c_str));
}
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
// Creates a UTF-16 wide string from the given ANSI string, allocating
// memory using new. The caller is responsible for deleting the return
// value using delete[]. Returns the wide string, or NULL if the
@@ -863,7 +850,7 @@ const char* String::Utf16ToAnsi(LPCWSTR utf16_str) {
return ansi;
}
-#endif // _WIN32_WCE
+#endif // GTEST_OS_WINDOWS_MOBILE
// Compares two C strings. Returns true iff they have the same content.
//
@@ -882,17 +869,17 @@ bool String::CStringEquals(const char * lhs, const char * rhs) {
// Converts an array of wide chars to a narrow string using the UTF-8
// encoding, and streams the result to the given Message object.
-static void StreamWideCharsToMessage(const wchar_t* wstr, size_t len,
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
Message* msg) {
// TODO(wan): consider allowing a testing::String object to
// contain '\0'. This will make it behave more like std::string,
// and will allow ToUtf8String() to return the correct encoding
// for '\0' s.t. we can get rid of the conditional here (and in
// several other places).
- for (size_t i = 0; i != len; ) { // NOLINT
+ for (size_t i = 0; i != length; ) { // NOLINT
if (wstr[i] != L'\0') {
- *msg << WideStringToUtf8(wstr + i, static_cast<int>(len - i));
- while (i != len && wstr[i] != L'\0')
+ *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+ while (i != length && wstr[i] != L'\0')
i++;
} else {
*msg << '\0';
@@ -1337,7 +1324,7 @@ namespace {
AssertionResult HRESULTFailureHelper(const char* expr,
const char* expected,
long hr) { // NOLINT
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
// Windows CE doesn't support FormatMessage.
const char error_text[] = "";
#else
@@ -1361,7 +1348,7 @@ AssertionResult HRESULTFailureHelper(const char* expr,
--message_length) {
error_text[message_length - 1] = '\0';
}
-#endif // _WIN32_WCE
+#endif // GTEST_OS_WINDOWS_MOBILE
const String error_hex(String::Format("0x%08X ", hr));
Message msg;
@@ -1455,17 +1442,8 @@ char* CodePointToUtf8(UInt32 code_point, char* str) {
// the terminating nul character). We are asking for 32 character
// buffer just in case. This is also enough for strncpy to
// null-terminate the destination string.
- // MSVC 8 deprecates strncpy(), so we want to suppress warning
- // 4996 (deprecated function) there.
-#if GTEST_OS_WINDOWS // We are on Windows.
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
-#endif
- strncpy(str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(),
- 32);
-#if GTEST_OS_WINDOWS // We are on Windows.
-#pragma warning(pop) // Restores the warning state.
-#endif
+ posix::StrNCpy(
+ str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32);
str[31] = '\0'; // Makes sure no change in the format to strncpy leaves
// the result unterminated.
}
@@ -1603,15 +1581,11 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
// NULL C string is considered different to any non-NULL C string,
// including the empty string.
bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
- if ( lhs == NULL ) return rhs == NULL;
-
- if ( rhs == NULL ) return false;
-
-#if GTEST_OS_WINDOWS
- return _stricmp(lhs, rhs) == 0;
-#else // GTEST_OS_WINDOWS
- return strcasecmp(lhs, rhs) == 0;
-#endif // GTEST_OS_WINDOWS
+ if (lhs == NULL)
+ return rhs == NULL;
+ if (rhs == NULL)
+ return false;
+ return posix::StrCaseCmp(lhs, rhs) == 0;
}
// Compares two wide C strings, ignoring case. Returns true iff they
@@ -1648,24 +1622,30 @@ bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
#endif // OS selector
}
-// Constructs a String by copying a given number of chars from a
-// buffer. E.g. String("hello", 3) will create the string "hel".
-String::String(const char * buffer, size_t len) {
- char * const temp = new char[ len + 1 ];
- memcpy(temp, buffer, len);
- temp[ len ] = '\0';
- c_str_ = temp;
-}
-
// Compares this with another String.
// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
// if this is greater than rhs.
int String::Compare(const String & rhs) const {
- if ( c_str_ == NULL ) {
- return rhs.c_str_ == NULL ? 0 : -1; // NULL < anything except NULL
+ const char* const lhs_c_str = c_str();
+ const char* const rhs_c_str = rhs.c_str();
+
+ if (lhs_c_str == NULL) {
+ return rhs_c_str == NULL ? 0 : -1; // NULL < anything except NULL
+ } else if (rhs_c_str == NULL) {
+ return 1;
}
- return rhs.c_str_ == NULL ? 1 : strcmp(c_str_, rhs.c_str_);
+ const size_t shorter_str_len =
+ length() <= rhs.length() ? length() : rhs.length();
+ for (size_t i = 0; i != shorter_str_len; i++) {
+ if (lhs_c_str[i] < rhs_c_str[i]) {
+ return -1;
+ } else if (lhs_c_str[i] > rhs_c_str[i]) {
+ return 1;
+ }
+ }
+ return (length() < rhs.length()) ? -1 :
+ (length() > rhs.length()) ? 1 : 0;
}
// Returns true iff this String ends with the given suffix. *Any*
@@ -1673,12 +1653,12 @@ int String::Compare(const String & rhs) const {
bool String::EndsWith(const char* suffix) const {
if (suffix == NULL || CStringEquals(suffix, "")) return true;
- if (c_str_ == NULL) return false;
+ if (c_str() == NULL) return false;
- const size_t this_len = strlen(c_str_);
+ const size_t this_len = strlen(c_str());
const size_t suffix_len = strlen(suffix);
return (this_len >= suffix_len) &&
- CStringEquals(c_str_ + this_len - suffix_len, suffix);
+ CStringEquals(c_str() + this_len - suffix_len, suffix);
}
// Returns true iff this String ends with the given suffix, ignoring case.
@@ -1686,37 +1666,12 @@ bool String::EndsWith(const char* suffix) const {
bool String::EndsWithCaseInsensitive(const char* suffix) const {
if (suffix == NULL || CStringEquals(suffix, "")) return true;
- if (c_str_ == NULL) return false;
+ if (c_str() == NULL) return false;
- const size_t this_len = strlen(c_str_);
+ const size_t this_len = strlen(c_str());
const size_t suffix_len = strlen(suffix);
return (this_len >= suffix_len) &&
- CaseInsensitiveCStringEquals(c_str_ + this_len - suffix_len, suffix);
-}
-
-// Sets the 0-terminated C string this String object represents. The
-// old string in this object is deleted, and this object will own a
-// clone of the input string. This function copies only up to length
-// bytes (plus a terminating null byte), or until the first null byte,
-// whichever comes first.
-//
-// This function works even when the c_str parameter has the same
-// value as that of the c_str_ field.
-void String::Set(const char * c_str, size_t length) {
- // Makes sure this works when c_str == c_str_
- const char* const temp = CloneString(c_str, length);
- delete[] c_str_;
- c_str_ = temp;
-}
-
-// Assigns a C string to this object. Self-assignment works.
-const String& String::operator=(const char* c_str) {
- // Makes sure this works when c_str == c_str_
- if (c_str != c_str_) {
- delete[] c_str_;
- c_str_ = CloneCString(c_str);
- }
- return *this;
+ CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix);
}
// Formats a list of arguments to a String, using the same format
@@ -1726,28 +1681,38 @@ const String& String::operator=(const char* c_str) {
// available.
//
// The result is limited to 4096 characters (including the tailing 0).
-// If 4096 characters are not enough to format the input,
-// "<buffer exceeded>" is returned.
+// If 4096 characters are not enough to format the input, or if
+// there's an error, "<formatting error or buffer exceeded>" is
+// returned.
String String::Format(const char * format, ...) {
va_list args;
va_start(args, format);
char buffer[4096];
+ const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
+
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
// 4996 (deprecated function) there.
-#if GTEST_OS_WINDOWS // We are on Windows.
+#ifdef _MSC_VER // We are using MSVC.
#pragma warning(push) // Saves the current warning state.
#pragma warning(disable:4996) // Temporarily disables warning 4996.
- const int size =
- vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
+ const int size = vsnprintf(buffer, kBufferSize, format, args);
#pragma warning(pop) // Restores the warning state.
-#else // We are on Linux or Mac OS.
- const int size =
- vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
-#endif // GTEST_OS_WINDOWS
+#else // We are not using MSVC.
+ const int size = vsnprintf(buffer, kBufferSize, format, args);
+#endif // _MSC_VER
va_end(args);
- return String(size >= 0 ? buffer : "<buffer exceeded>");
+ // vsnprintf()'s behavior is not portable. When the buffer is not
+ // big enough, it returns a negative value in MSVC, and returns the
+ // needed buffer size on Linux. When there is an output error, it
+ // always returns a negative value. For simplicity, we lump the two
+ // error cases together.
+ if (size < 0 || size >= kBufferSize) {
+ return String("<formatting error or buffer exceeded>");
+ } else {
+ return String(buffer, size);
+ }
}
// Converts the buffer in a StrStream to a String, converting NUL
@@ -1798,11 +1763,15 @@ String AppendUserMessage(const String& gtest_msg,
return msg.GetString();
}
+} // namespace internal
+
// class TestResult
// Creates an empty TestResult.
TestResult::TestResult()
- : death_test_count_(0),
+ : test_part_results_(new internal::Vector<TestPartResult>),
+ test_properties_(new internal::Vector<TestProperty>),
+ death_test_count_(0),
elapsed_time_(0) {
}
@@ -1810,9 +1779,28 @@ TestResult::TestResult()
TestResult::~TestResult() {
}
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+ return test_part_results_->GetElement(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+ return test_properties_->GetElement(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+ test_part_results_->Clear();
+}
+
// Adds a test part result to the list.
void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
- test_part_results_.PushBack(test_part_result);
+ test_part_results_->PushBack(test_part_result);
}
// Adds a test property to the list. If a property with the same key as the
@@ -1822,21 +1810,21 @@ void TestResult::RecordProperty(const TestProperty& test_property) {
if (!ValidateTestProperty(test_property)) {
return;
}
- MutexLock lock(&test_properites_mutex_);
- ListNode<TestProperty>* const node_with_matching_key =
- test_properties_.FindIf(TestPropertyKeyIs(test_property.key()));
- if (node_with_matching_key == NULL) {
- test_properties_.PushBack(test_property);
+ internal::MutexLock lock(&test_properites_mutex_);
+ TestProperty* const property_with_matching_key =
+ test_properties_->FindIf(
+ internal::TestPropertyKeyIs(test_property.key()));
+ if (property_with_matching_key == NULL) {
+ test_properties_->PushBack(test_property);
return;
}
- TestProperty& property_with_matching_key = node_with_matching_key->element();
- property_with_matching_key.SetValue(test_property.value());
+ property_with_matching_key->SetValue(test_property.value());
}
// Adds a failure if the key is a reserved attribute of Google Test
// testcase tags. Returns true if the property is valid.
bool TestResult::ValidateTestProperty(const TestProperty& test_property) {
- String key(test_property.key());
+ internal::String key(test_property.key());
if (key == "name" || key == "status" || key == "time" || key == "classname") {
ADD_FAILURE()
<< "Reserved key used in RecordProperty(): "
@@ -1850,49 +1838,51 @@ bool TestResult::ValidateTestProperty(const TestProperty& test_property) {
// Clears the object.
void TestResult::Clear() {
- test_part_results_.Clear();
- test_properties_.Clear();
+ test_part_results_->Clear();
+ test_properties_->Clear();
death_test_count_ = 0;
elapsed_time_ = 0;
}
-// Returns true iff the test part passed.
-static bool TestPartPassed(const TestPartResult & result) {
- return result.passed();
-}
-
-// Gets the number of successful test parts.
-int TestResult::successful_part_count() const {
- return test_part_results_.CountIf(TestPartPassed);
-}
-
-// Returns true iff the test part failed.
-static bool TestPartFailed(const TestPartResult & result) {
- return result.failed();
-}
-
-// Gets the number of failed test parts.
-int TestResult::failed_part_count() const {
- return test_part_results_.CountIf(TestPartFailed);
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+ for (int i = 0; i < total_part_count(); ++i) {
+ if (GetTestPartResult(i).failed())
+ return true;
+ }
+ return false;
}
// Returns true iff the test part fatally failed.
-static bool TestPartFatallyFailed(const TestPartResult & result) {
+static bool TestPartFatallyFailed(const TestPartResult& result) {
return result.fatally_failed();
}
// Returns true iff the test fatally failed.
bool TestResult::HasFatalFailure() const {
- return test_part_results_.CountIf(TestPartFatallyFailed) > 0;
+ return test_part_results_->CountIf(TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+ return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+ return test_part_results_->CountIf(TestPartNonfatallyFailed) > 0;
}
// Gets the number of all test parts. This is the sum of the number
// of successful test parts and the number of failed test parts.
int TestResult::total_part_count() const {
- return test_part_results_.size();
+ return test_part_results_->size();
}
-} // namespace internal
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+ return test_properties_->size();
+}
// class Test
@@ -1932,6 +1922,22 @@ void Test::RecordProperty(const char* key, int value) {
RecordProperty(key, value_message.GetString().c_str());
}
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+ const String& message) {
+ // This function is a friend of UnitTest and as such has access to
+ // AddTestPartResult.
+ UnitTest::GetInstance()->AddTestPartResult(
+ result_type,
+ NULL, // No info about the source file where the exception occurred.
+ -1, // We have no info on which line caused the exception.
+ message,
+ String()); // No stack trace, either.
+}
+
+} // namespace internal
+
#if GTEST_OS_WINDOWS
// We are on Windows.
@@ -1942,15 +1948,8 @@ static void AddExceptionThrownFailure(DWORD exception_code,
message << "Exception thrown with code 0x" << std::setbase(16) <<
exception_code << std::setbase(10) << " in " << location << ".";
- UnitTest* const unit_test = UnitTest::GetInstance();
- unit_test->AddTestPartResult(
- TPRT_FATAL_FAILURE,
- static_cast<const char *>(NULL),
- // We have no info about the source file where the exception
- // occurred.
- -1, // We have no info on which line caused the exception.
- message.GetString(),
- internal::String(""));
+ internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+ message.GetString());
}
#endif // GTEST_OS_WINDOWS
@@ -1966,7 +1965,7 @@ bool Test::HasSameFixtureClass() {
// Info about the first test in the current test case.
const internal::TestInfoImpl* const first_test_info =
- test_case->test_info_list().Head()->element()->impl();
+ test_case->test_info_list().GetElement(0)->impl();
const internal::TypeId first_fixture_id = first_test_info->fixture_class_id();
const char* const first_test_name = first_test_info->name();
@@ -2028,8 +2027,8 @@ void Test::Run() {
if (!HasSameFixtureClass()) return;
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
-#if GTEST_OS_WINDOWS && !defined(__MINGW32__)
- // We are on Windows.
+#if GTEST_HAS_SEH
+ // Catch SEH-style exceptions.
impl->os_stack_trace_getter()->UponLeavingGTest();
__try {
SetUp();
@@ -2060,7 +2059,7 @@ void Test::Run() {
AddExceptionThrownFailure(GetExceptionCode(), "TearDown()");
}
-#else // We are on Linux, Mac or MingW - exceptions are disabled.
+#else // We are on a compiler or platform that doesn't support SEH.
impl->os_stack_trace_getter()->UponLeavingGTest();
SetUp();
@@ -2075,7 +2074,7 @@ void Test::Run() {
// failed.
impl->os_stack_trace_getter()->UponLeavingGTest();
TearDown();
-#endif // GTEST_OS_WINDOWS
+#endif // GTEST_HAS_SEH
}
@@ -2084,6 +2083,12 @@ bool Test::HasFatalFailure() {
return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
}
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+ return internal::GetUnitTestImpl()->current_test_result()->
+ HasNonfatalFailure();
+}
+
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
@@ -2181,8 +2186,11 @@ const char* TestInfo::comment() const {
// Returns true if this test should run.
bool TestInfo::should_run() const { return impl_->should_run(); }
+// Returns true if this test matches the user-specified filter.
+bool TestInfo::matches_filter() const { return impl_->matches_filter(); }
+
// Returns the result of the test.
-const internal::TestResult* TestInfo::result() const { return impl_->result(); }
+const TestResult* TestInfo::result() const { return impl_->result(); }
// Increments the number of death tests encountered in this test so
// far.
@@ -2219,17 +2227,6 @@ class TestNameIs {
} // namespace
-// Finds and returns a TestInfo with the given name. If one doesn't
-// exist, returns NULL.
-TestInfo * TestCase::GetTestInfo(const char* test_name) {
- // Can we find a TestInfo with the given name?
- internal::ListNode<TestInfo *> * const node = test_info_list_->FindIf(
- TestNameIs(test_name));
-
- // Returns the TestInfo found.
- return node ? node->element() : NULL;
-}
-
namespace internal {
// This method expands all parameterized tests registered with macros TEST_P
@@ -2253,17 +2250,16 @@ void TestInfoImpl::Run() {
UnitTestImpl* const impl = internal::GetUnitTestImpl();
impl->set_current_test_info(parent_);
- // Notifies the unit test event listener that a test is about to
- // start.
- UnitTestEventListenerInterface* const result_printer =
- impl->result_printer();
- result_printer->OnTestStart(parent_);
+ TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+ // Notifies the unit test event listeners that a test is about to start.
+ repeater->OnTestStart(*parent_);
const TimeInMillis start = GetTimeInMillis();
impl->os_stack_trace_getter()->UponLeavingGTest();
-#if GTEST_OS_WINDOWS && !defined(__MINGW32__)
- // We are on Windows.
+#if GTEST_HAS_SEH
+ // Catch SEH-style exceptions.
Test* test = NULL;
__try {
@@ -2275,7 +2271,7 @@ void TestInfoImpl::Run() {
"the test fixture's constructor");
return;
}
-#else // We are on Linux, Mac OS or MingW - exceptions are disabled.
+#else // We are on a compiler or platform that doesn't support SEH.
// TODO(wan): If test->Run() throws, test won't be deleted. This is
// not a problem now as we don't use exceptions. If we were to
@@ -2284,7 +2280,7 @@ void TestInfoImpl::Run() {
// Creates the test object.
Test* test = factory_->CreateTest();
-#endif // GTEST_OS_WINDOWS
+#endif // GTEST_HAS_SEH
// Runs the test only if the constructor of the test fixture didn't
// generate a fatal failure.
@@ -2300,7 +2296,7 @@ void TestInfoImpl::Run() {
result_.set_elapsed_time(GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished.
- result_printer->OnTestEnd(parent_);
+ repeater->OnTestEnd(*parent_);
// Tells UnitTest to stop associating assertion results to this
// test.
@@ -2347,27 +2343,39 @@ TestCase::TestCase(const char* name, const char* comment,
Test::TearDownTestCaseFunc tear_down_tc)
: name_(name),
comment_(comment),
+ test_info_list_(new internal::Vector<TestInfo*>),
+ test_indices_(new internal::Vector<int>),
set_up_tc_(set_up_tc),
tear_down_tc_(tear_down_tc),
should_run_(false),
elapsed_time_(0) {
- test_info_list_ = new internal::List<TestInfo *>;
}
// Destructor of TestCase.
TestCase::~TestCase() {
// Deletes every Test in the collection.
test_info_list_->ForEach(internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+ const int index = test_indices_->GetElementOr(i, -1);
+ return index < 0 ? NULL : test_info_list_->GetElement(index);
+}
- // Then deletes the Test collection.
- delete test_info_list_;
- test_info_list_ = NULL;
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+ const int index = test_indices_->GetElementOr(i, -1);
+ return index < 0 ? NULL : test_info_list_->GetElement(index);
}
// Adds a test to this test case. Will delete the test upon
// destruction of the TestCase object.
void TestCase::AddTestInfo(TestInfo * test_info) {
test_info_list_->PushBack(test_info);
+ test_indices_->PushBack(test_indices_->size());
}
// Runs every test in this TestCase.
@@ -2377,20 +2385,21 @@ void TestCase::Run() {
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
impl->set_current_test_case(this);
- UnitTestEventListenerInterface * const result_printer =
- impl->result_printer();
+ TestEventListener* repeater = UnitT