Makes List a random-access data structure. This simplifies the implementation and makes it easier to implement test shuffling.

This commit is contained in:
zhanyong.wan 2009-07-01 22:55:05 +00:00
parent b2db677c99
commit 600105ee3a
7 changed files with 325 additions and 440 deletions

View File

@ -434,13 +434,14 @@ class TestResult {
TimeInMillis elapsed_time() const { return elapsed_time_; } TimeInMillis elapsed_time() const { return elapsed_time_; }
// Returns the i-th test part result among all the results. i can range // Returns the i-th test part result among all the results. i can range
// from 0 to test_property_count() - 1. If i is not in that range, returns // from 0 to test_property_count() - 1. If i is not in that range, aborts
// NULL. // the program.
const TestPartResult* GetTestPartResult(int i) const; const TestPartResult& GetTestPartResult(int i) const;
// Returns the i-th test property. i can range from 0 to // Returns the i-th test property. i can range from 0 to
// test_property_count() - 1. If i is not in that range, returns NULL. // test_property_count() - 1. If i is not in that range, aborts the
const TestProperty* GetTestProperty(int i) const; // program.
const TestProperty& GetTestProperty(int i) const;
private: private:
friend class DefaultGlobalTestPartResultReporter; friend class DefaultGlobalTestPartResultReporter;

View File

@ -116,9 +116,7 @@ class ScopedTrace; // Implements scoped trace.
class TestInfoImpl; // Opaque implementation of TestInfo class TestInfoImpl; // Opaque implementation of TestInfo
class TestResult; // Result of a single Test. class TestResult; // Result of a single Test.
class UnitTestImpl; // Opaque implementation of UnitTest class UnitTestImpl; // Opaque implementation of UnitTest
template <typename E> class List; // A generic list. template <typename E> class List; // A generic list.
template <typename E> class ListNode; // A node in a generic list.
// How many times InitGoogleTest() has been called. // How many times InitGoogleTest() has been called.
extern int g_init_gtest_count; extern int g_init_gtest_count;

View File

@ -49,7 +49,8 @@
#include <errno.h> #include <errno.h>
#endif // !_WIN32_WCE #endif // !_WIN32_WCE
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> // For strtoll/_strtoul64. #include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
#include <string.h> // For memmove.
#include <string> #include <string>
@ -198,199 +199,74 @@ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
// method. Assumes that 0 <= shard_index < total_shards. // method. Assumes that 0 <= shard_index < total_shards.
bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id); bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id);
// List is a simple singly-linked list container. // List is an ordered container that supports random access to the
// elements.
// //
// We cannot use std::list as Microsoft's implementation of STL has // We cannot use std::vector, as Visual C++ 7.1's implementation of
// problems when exception is disabled. There is a hack to work // STL has problems compiling when exceptions are disabled. There is
// around this, but we've seen cases where the hack fails to work. // a hack to work around the problems, but we've seen cases where the
// hack fails to work.
// //
// TODO(wan): switch to std::list when we have a reliable fix for the // The element type must support copy constructor and operator=.
// STL problem, e.g. when we upgrade to the next version of Visual
// C++, or (more likely) switch to STLport.
//
// The element type must support copy constructor.
// Forward declare List
template <typename E> // E is the element type.
class List;
// ListNode is a node in a singly-linked list. It consists of an
// element and a pointer to the next node. The last node in the list
// has a NULL value for its next pointer.
template <typename E> // E is the element type.
class ListNode {
friend class List<E>;
private:
E element_;
ListNode * next_;
// The c'tor is private s.t. only in the ListNode class and in its
// friend class List we can create a ListNode object.
//
// Creates a node with a given element value. The next pointer is
// set to NULL.
//
// ListNode does NOT have a default constructor. Always use this
// constructor (with parameter) to create a ListNode object.
explicit ListNode(const E & element) : element_(element), next_(NULL) {}
// We disallow copying ListNode
GTEST_DISALLOW_COPY_AND_ASSIGN_(ListNode);
public:
// Gets the element in this node.
E & element() { return element_; }
const E & element() const { return element_; }
// Gets the next node in the list.
ListNode * next() { return next_; }
const ListNode * next() const { return next_; }
};
// List is a simple singly-linked list container.
template <typename E> // E is the element type. template <typename E> // E is the element type.
class List { class List {
public: public:
// Creates an empty list. // Creates an empty list.
List() : head_(NULL), last_(NULL), size_(0), List() : elements_(NULL), capacity_(0), size_(0) {}
last_read_index_(-1), last_read_(NULL) {}
// D'tor. // D'tor.
virtual ~List(); virtual ~List() { Clear(); }
// Clears the list. // Clears the list.
void Clear() { void Clear() {
if ( size_ > 0 ) { if (elements_ != NULL) {
// 1. Deletes every node. for (int i = 0; i < size_; i++) {
ListNode<E> * node = head_; delete elements_[i];
ListNode<E> * next = node->next();
for ( ; ; ) {
delete node;
node = next;
if ( node == NULL ) break;
next = node->next();
} }
// 2. Resets the member variables. free(elements_);
last_read_ = head_ = last_ = NULL; elements_ = NULL;
size_ = 0; capacity_ = size_ = 0;
last_read_index_ = -1;
} }
} }
// Gets the number of elements. // Gets the number of elements.
int size() const { return size_; } int size() const { return size_; }
// Returns true if the list is empty.
bool IsEmpty() const { return size() == 0; }
// Gets the first element of the list, or NULL if the list is empty.
ListNode<E> * Head() { return head_; }
const ListNode<E> * Head() const { return head_; }
// Gets the last element of the list, or NULL if the list is empty.
ListNode<E> * Last() { return last_; }
const ListNode<E> * Last() const { return last_; }
// Adds an element to the end of the list. A copy of the element is // Adds an element to the end of the list. A copy of the element is
// created using the copy constructor, and then stored in the list. // created using the copy constructor, and then stored in the list.
// Changes made to the element in the list doesn't affect the source // Changes made to the element in the list doesn't affect the source
// object, and vice versa. This does not affect the "last read" // object, and vice versa.
// index. void PushBack(const E & element) { Insert(element, size_); }
void PushBack(const E & element) {
ListNode<E> * new_node = new ListNode<E>(element);
if ( size_ == 0 ) { // Adds an element to the beginning of this list.
head_ = last_ = new_node; void PushFront(const E& element) { Insert(element, 0); }
size_ = 1;
} else {
last_->next_ = new_node;
last_ = new_node;
size_++;
}
}
// Adds an element to the beginning of this list. The "last read"
// index is adjusted accordingly.
void PushFront(const E& element) {
ListNode<E>* const new_node = new ListNode<E>(element);
if ( size_ == 0 ) {
head_ = last_ = new_node;
size_ = 1;
} else {
new_node->next_ = head_;
head_ = new_node;
size_++;
}
if (last_read_index_ >= 0) {
// A new element at the head bumps up an existing index by 1.
last_read_index_++;
}
}
// Removes an element from the beginning of this list. If the // Removes an element from the beginning of this list. If the
// result argument is not NULL, the removed element is stored in the // result argument is not NULL, the removed element is stored in the
// memory it points to. Otherwise the element is thrown away. // memory it points to. Otherwise the element is thrown away.
// Returns true iff the list wasn't empty before the operation. The // Returns true iff the list wasn't empty before the operation.
// "last read" index is adjusted accordingly.
bool PopFront(E* result) { bool PopFront(E* result) {
if (size_ == 0) return false; if (size_ == 0)
return false;
if (result != NULL) { if (result != NULL)
*result = head_->element_; *result = *(elements_[0]);
}
ListNode<E>* const old_head = head_; delete elements_[0];
size_--; size_--;
if (size_ == 0) { MoveElements(1, size_, 0);
head_ = last_ = NULL;
} else {
head_ = head_->next_;
}
delete old_head;
if (last_read_index_ > 0) {
last_read_index_--;
} else if (last_read_index_ == 0) {
last_read_index_ = -1;
last_read_ = NULL;
}
return true; return true;
} }
// Inserts an element after a given node in the list. It's the // Inserts an element at the given index. It's the caller's
// caller's responsibility to ensure that the given node is in the // responsibility to ensure that the given index is in the range [0,
// list. If the given node is NULL, inserts the element at the // size()].
// front of the list. The "last read" index is adjusted void Insert(const E& element, int index) {
// accordingly. GrowIfNeeded();
ListNode<E>* InsertAfter(ListNode<E>* node, const E& element) { MoveElements(index, size_ - index, index + 1);
if (node == NULL) { elements_[index] = new E(element);
PushFront(element);
return Head();
}
ListNode<E>* const new_node = new ListNode<E>(element);
new_node->next_ = node->next_;
node->next_ = new_node;
size_++; size_++;
if (node == last_) {
last_ = new_node;
}
// We aren't sure whether this insertion will affect the last read
// index, so we invalidate it to be safe.
last_read_index_ = -1;
last_read_ = NULL;
return new_node;
} }
// Returns the number of elements that satisfy a given predicate. // Returns the number of elements that satisfy a given predicate.
@ -399,10 +275,8 @@ class List {
template <typename P> // P is the type of the predicate function/functor template <typename P> // P is the type of the predicate function/functor
int CountIf(P predicate) const { int CountIf(P predicate) const {
int count = 0; int count = 0;
for ( const ListNode<E> * node = Head(); for (int i = 0; i < size_; i++) {
node != NULL; if (predicate(*(elements_[i]))) {
node = node->next() ) {
if ( predicate(node->element()) ) {
count++; count++;
} }
} }
@ -416,10 +290,8 @@ class List {
// the elements. // the elements.
template <typename F> // F is the type of the function/functor template <typename F> // F is the type of the function/functor
void ForEach(F functor) const { void ForEach(F functor) const {
for ( const ListNode<E> * node = Head(); for (int i = 0; i < size_; i++) {
node != NULL; functor(*(elements_[i]));
node = node->next() ) {
functor(node->element());
} }
} }
@ -428,81 +300,70 @@ class List {
// function/functor that accepts a 'const E &', where E is the // function/functor that accepts a 'const E &', where E is the
// element type. This method does not change the elements. // element type. This method does not change the elements.
template <typename P> // P is the type of the predicate function/functor. template <typename P> // P is the type of the predicate function/functor.
const ListNode<E> * FindIf(P predicate) const { const E* FindIf(P predicate) const {
for ( const ListNode<E> * node = Head(); for (int i = 0; i < size_; i++) {
node != NULL; if (predicate(*elements_[i])) {
node = node->next() ) { return elements_[i];
if ( predicate(node->element()) ) {
return node;
} }
} }
return NULL; return NULL;
} }
template <typename P> template <typename P>
ListNode<E> * FindIf(P predicate) { E* FindIf(P predicate) {
for ( ListNode<E> * node = Head(); for (int i = 0; i < size_; i++) {
node != NULL; if (predicate(*elements_[i])) {
node = node->next() ) { return elements_[i];
if ( predicate(node->element() ) ) {
return node;
} }
} }
return NULL; return NULL;
} }
// Returns a pointer to the i-th element of the list, or NULL if i is not // Returns the i-th element of the list, or aborts the program if i
// in range [0, size()). The "last read" index is adjusted accordingly. // is not in range [0, size()).
const E* GetElement(int i) const { const E& GetElement(int i) const {
if (i < 0 || i >= size()) GTEST_CHECK_(0 <= i && i < size_)
return NULL; << "Invalid list index " << i << ": must be in range [0, "
<< (size_ - 1) << "].";
if (last_read_index_ < 0 || last_read_index_ > i) { return *(elements_[i]);
// We have to count from the start.
last_read_index_ = 0;
last_read_ = Head();
}
while (last_read_index_ < i) {
last_read_ = last_read_->next();
last_read_index_++;
}
return &(last_read_->element());
} }
// Returns the i-th element of the list, or default_value if i is not // Returns the i-th element of the list, or default_value if i is not
// in range [0, size()). The "last read" index is adjusted accordingly. // in range [0, size()).
E GetElementOr(int i, E default_value) const { E GetElementOr(int i, E default_value) const {
const E* element = GetElement(i); return (i < 0 || i >= size_) ? default_value : *(elements_[i]);
return element ? *element : default_value;
} }
private: private:
ListNode<E>* head_; // The first node of the list. // Grows the buffer if it is not big enough to hold one more element.
ListNode<E>* last_; // The last node of the list. void GrowIfNeeded() {
int size_; // The number of elements in the list. if (size_ < capacity_)
return;
// These fields point to the last element read via GetElement(i) or // Exponential bump-up is necessary to ensure that inserting N
// GetElementOr(i). They are used to speed up list traversal as // elements is O(N) instead of O(N^2). The factor 3/2 means that
// often they allow us to find the wanted element by looking from // no more than 1/3 of the slots are wasted.
// the last visited one instead of the list head. This means a const int new_capacity = 3*(capacity_/2 + 1);
// sequential traversal of the list can be done in O(N) time instead GTEST_CHECK_(new_capacity > capacity_) // Does the new capacity overflow?
// of O(N^2). << "Cannot grow a list with " << capacity_ << " elements already.";
mutable int last_read_index_; capacity_ = new_capacity;
mutable const ListNode<E>* last_read_; elements_ = static_cast<E**>(
realloc(elements_, capacity_*sizeof(elements_[0])));
}
// Moves the give consecutive elements to a new index in the list.
void MoveElements(int source, int count, int dest) {
memmove(elements_ + dest, elements_ + source, count*sizeof(elements_[0]));
}
E** elements_;
int capacity_; // The number of elements allocated for elements_.
int size_; // The number of elements; in the range [0, capacity_].
// We disallow copying List. // We disallow copying List.
GTEST_DISALLOW_COPY_AND_ASSIGN_(List); GTEST_DISALLOW_COPY_AND_ASSIGN_(List);
}; }; // class List
// The virtual destructor of List.
template <typename E>
List<E>::~List() {
Clear();
}
// A function for deleting an object. Handy for being used as a // A function for deleting an object. Handy for being used as a
// functor. // functor.
@ -907,10 +768,8 @@ class UnitTestImpl {
// before main() is reached. // before main() is reached.
if (original_working_dir_.IsEmpty()) { if (original_working_dir_.IsEmpty()) {
original_working_dir_.Set(FilePath::GetCurrentDir()); original_working_dir_.Set(FilePath::GetCurrentDir());
if (original_working_dir_.IsEmpty()) { GTEST_CHECK_(!original_working_dir_.IsEmpty())
printf("%s\n", "Failed to get the current working directory."); << "Failed to get the current working directory.";
posix::Abort();
}
} }
GetTestCase(test_info->test_case_name(), GetTestCase(test_info->test_case_name(),
@ -1057,8 +916,8 @@ class UnitTestImpl {
bool parameterized_tests_registered_; bool parameterized_tests_registered_;
#endif // GTEST_HAS_PARAM_TEST #endif // GTEST_HAS_PARAM_TEST
// Points to the last death test case registered. Initially NULL. // Index of the last death test case registered. Initially -1.
internal::ListNode<TestCase*>* last_death_test_case_; int last_death_test_case_;
// This points to the TestCase for the currently running test. It // This points to the TestCase for the currently running test. It
// changes as Google Test goes through one test case after another. // changes as Google Test goes through one test case after another.

View File

@ -86,12 +86,7 @@ const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
internal::posix::Abort(); internal::posix::Abort();
} }
const internal::ListNode<TestPartResult>* p = list_->Head(); return list_->GetElement(index);
for (int i = 0; i < index; i++) {
p = p->next();
}
return p->element();
} }
// Returns the number of TestPartResult objects in the array. // Returns the number of TestPartResult objects in the array.

View File

@ -264,10 +264,8 @@ static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
static int SumOverTestCaseList(const internal::List<TestCase*>& case_list, static int SumOverTestCaseList(const internal::List<TestCase*>& case_list,
int (TestCase::*method)() const) { int (TestCase::*method)() const) {
int sum = 0; int sum = 0;
for (const internal::ListNode<TestCase*>* node = case_list.Head(); for (int i = 0; i < case_list.size(); i++) {
node != NULL; sum += (case_list.GetElement(i)->*method)();
node = node->next()) {
sum += (node->element()->*method)();
} }
return sum; return sum;
} }
@ -1830,16 +1828,17 @@ TestResult::TestResult()
TestResult::~TestResult() { TestResult::~TestResult() {
} }
// Returns the i-th test part result among all the results. i can range // Returns the i-th test part result among all the results. i can
// from 0 to total_part_count() - 1. If i is not in that range, returns // range from 0 to total_part_count() - 1. If i is not in that range,
// NULL. // aborts the program.
const TestPartResult* TestResult::GetTestPartResult(int i) const { const TestPartResult& TestResult::GetTestPartResult(int i) const {
return test_part_results_->GetElement(i); return test_part_results_->GetElement(i);
} }
// Returns the i-th test property. i can range from 0 to // Returns the i-th test property. i can range from 0 to
// test_property_count() - 1. If i is not in that range, returns NULL. // test_property_count() - 1. If i is not in that range, aborts the
const TestProperty* TestResult::GetTestProperty(int i) const { // program.
const TestProperty& TestResult::GetTestProperty(int i) const {
return test_properties_->GetElement(i); return test_properties_->GetElement(i);
} }
@ -1861,14 +1860,13 @@ void TestResult::RecordProperty(const TestProperty& test_property) {
return; return;
} }
MutexLock lock(&test_properites_mutex_); MutexLock lock(&test_properites_mutex_);
ListNode<TestProperty>* const node_with_matching_key = TestProperty* const property_with_matching_key =
test_properties_->FindIf(TestPropertyKeyIs(test_property.key())); test_properties_->FindIf(TestPropertyKeyIs(test_property.key()));
if (node_with_matching_key == NULL) { if (property_with_matching_key == NULL) {
test_properties_->PushBack(test_property); test_properties_->PushBack(test_property);
return; 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 // Adds a failure if the key is a reserved attribute of Google Test
@ -2028,7 +2026,7 @@ bool Test::HasSameFixtureClass() {
// Info about the first test in the current test case. // Info about the first test in the current test case.
const internal::TestInfoImpl* const first_test_info = 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 internal::TypeId first_fixture_id = first_test_info->fixture_class_id();
const char* const first_test_name = first_test_info->name(); const char* const first_test_name = first_test_info->name();
@ -2884,7 +2882,6 @@ void PrettyUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
class UnitTestEventsRepeater : public UnitTestEventListenerInterface { class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
public: public:
typedef internal::List<UnitTestEventListenerInterface *> Listeners; typedef internal::List<UnitTestEventListenerInterface *> Listeners;
typedef internal::ListNode<UnitTestEventListenerInterface *> ListenersNode;
UnitTestEventsRepeater() {} UnitTestEventsRepeater() {}
virtual ~UnitTestEventsRepeater(); virtual ~UnitTestEventsRepeater();
void AddListener(UnitTestEventListenerInterface *listener); void AddListener(UnitTestEventListenerInterface *listener);
@ -2908,10 +2905,8 @@ class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
}; };
UnitTestEventsRepeater::~UnitTestEventsRepeater() { UnitTestEventsRepeater::~UnitTestEventsRepeater() {
for (ListenersNode* listener = listeners_.Head(); for (int i = 0; i < listeners_.size(); i++) {
listener != NULL; delete listeners_.GetElement(i);
listener = listener->next()) {
delete listener->element();
} }
} }
@ -2924,10 +2919,8 @@ void UnitTestEventsRepeater::AddListener(
// This defines a member that repeats the call to all listeners. // This defines a member that repeats the call to all listeners.
#define GTEST_REPEATER_METHOD_(Name, Type) \ #define GTEST_REPEATER_METHOD_(Name, Type) \
void UnitTestEventsRepeater::Name(const Type& parameter) { \ void UnitTestEventsRepeater::Name(const Type& parameter) { \
for (ListenersNode* listener = listeners_.Head(); \ for (int i = 0; i < listeners_.size(); i++) { \
listener != NULL; \ listeners_.GetElement(i)->Name(parameter); \
listener = listener->next()) { \
listener->element()->Name(parameter); \
} \ } \
} }
@ -3150,7 +3143,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
int failures = 0; int failures = 0;
for (int i = 0; i < result.total_part_count(); ++i) { for (int i = 0; i < result.total_part_count(); ++i) {
const TestPartResult& part = *result.GetTestPartResult(i); const TestPartResult& part = result.GetTestPartResult(i);
if (part.failed()) { if (part.failed()) {
const internal::String message = const internal::String message =
internal::String::Format("%s:%d\n%s", part.file_name(), internal::String::Format("%s:%d\n%s", part.file_name(),
@ -3212,7 +3205,7 @@ internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
using internal::TestProperty; using internal::TestProperty;
Message attributes; Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) { for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = *result.GetTestProperty(i); const TestProperty& property = result.GetTestProperty(i);
attributes << " " << property.key() << "=" attributes << " " << property.key() << "="
<< "\"" << EscapeXmlAttribute(property.value()) << "\""; << "\"" << EscapeXmlAttribute(property.value()) << "\"";
} }
@ -3407,11 +3400,9 @@ void UnitTest::AddTestPartResult(TestPartResultType result_type,
if (impl_->gtest_trace_stack()->size() > 0) { if (impl_->gtest_trace_stack()->size() > 0) {
msg << "\n" << GTEST_NAME_ << " trace:"; msg << "\n" << GTEST_NAME_ << " trace:";
for (internal::ListNode<internal::TraceInfo>* node = for (int i = 0; i < impl_->gtest_trace_stack()->size(); i++) {
impl_->gtest_trace_stack()->Head(); const internal::TraceInfo& trace =
node != NULL; impl_->gtest_trace_stack()->GetElement(i);
node = node->next()) {
const internal::TraceInfo& trace = node->element();
msg << "\n" << trace.file << ":" << trace.line << ": " << trace.message; msg << "\n" << trace.file << ":" << trace.line << ": " << trace.message;
} }
} }
@ -3606,7 +3597,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
parameterized_test_registry_(), parameterized_test_registry_(),
parameterized_tests_registered_(false), parameterized_tests_registered_(false),
#endif // GTEST_HAS_PARAM_TEST #endif // GTEST_HAS_PARAM_TEST
last_death_test_case_(NULL), last_death_test_case_(-1),
current_test_case_(NULL), current_test_case_(NULL),
current_test_info_(NULL), current_test_info_(NULL),
ad_hoc_test_result_(), ad_hoc_test_result_(),
@ -3670,30 +3661,27 @@ TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
Test::SetUpTestCaseFunc set_up_tc, Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc) { Test::TearDownTestCaseFunc tear_down_tc) {
// Can we find a TestCase with the given name? // Can we find a TestCase with the given name?
internal::ListNode<TestCase*>* node = test_cases_.FindIf( TestCase** test_case = test_cases_.FindIf(TestCaseNameIs(test_case_name));
TestCaseNameIs(test_case_name));
if (node == NULL) { if (test_case != NULL)
// No. Let's create one. return *test_case;
TestCase* const test_case =
// No. Let's create one.
TestCase* const new_test_case =
new TestCase(test_case_name, comment, set_up_tc, tear_down_tc); new TestCase(test_case_name, comment, set_up_tc, tear_down_tc);
// Is this a death test case? // Is this a death test case?
if (internal::UnitTestOptions::MatchesFilter(String(test_case_name), if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
kDeathTestCaseFilter)) { kDeathTestCaseFilter)) {
// Yes. Inserts the test case after the last death test case // Yes. Inserts the test case after the last death test case
// defined so far. // defined so far.
node = test_cases_.InsertAfter(last_death_test_case_, test_case); test_cases_.Insert(new_test_case, ++last_death_test_case_);
last_death_test_case_ = node; } else {
} else { // No. Appends to the end of the list.
// No. Appends to the end of the list. test_cases_.PushBack(new_test_case);
test_cases_.PushBack(test_case);
node = test_cases_.Last();
}
} }
// Returns the TestCase found. return new_test_case;
return node->element();
} }
// Helpers for setting up / tearing down the given environment. They // Helpers for setting up / tearing down the given environment. They
@ -3925,19 +3913,13 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
// this shard. // this shard.
int num_runnable_tests = 0; int num_runnable_tests = 0;
int num_selected_tests = 0; int num_selected_tests = 0;
for (const internal::ListNode<TestCase *> *test_case_node = for (int i = 0; i < test_cases_.size(); i++) {
test_cases_.Head(); TestCase* const test_case = test_cases_.GetElement(i);
test_case_node != NULL;
test_case_node = test_case_node->next()) {
TestCase * const test_case = test_case_node->element();
const String &test_case_name = test_case->name(); const String &test_case_name = test_case->name();
test_case->set_should_run(false); test_case->set_should_run(false);
for (const internal::ListNode<TestInfo *> *test_info_node = for (int j = 0; j < test_case->test_info_list().size(); j++) {
test_case->test_info_list().Head(); TestInfo* const test_info = test_case->test_info_list().GetElement(j);
test_info_node != NULL;
test_info_node = test_info_node->next()) {
TestInfo * const test_info = test_info_node->element();
const String test_name(test_info->name()); const String test_name(test_info->name());
// A test is disabled if test case name or test name matches // A test is disabled if test case name or test name matches
// kDisableTestFilter. // kDisableTestFilter.
@ -3974,17 +3956,13 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
// Prints the names of the tests matching the user-specified filter flag. // Prints the names of the tests matching the user-specified filter flag.
void UnitTestImpl::ListTestsMatchingFilter() { void UnitTestImpl::ListTestsMatchingFilter() {
for (const internal::ListNode<TestCase*>* test_case_node = test_cases_.Head(); for (int i = 0; i < test_cases_.size(); i++) {
test_case_node != NULL; const TestCase* const test_case = test_cases_.GetElement(i);
test_case_node = test_case_node->next()) {
const TestCase* const test_case = test_case_node->element();
bool printed_test_case_name = false; bool printed_test_case_name = false;
for (const internal::ListNode<TestInfo*>* test_info_node = for (int j = 0; j < test_case->test_info_list().size(); j++) {
test_case->test_info_list().Head(); const TestInfo* const test_info =
test_info_node != NULL; test_case->test_info_list().GetElement(j);
test_info_node = test_info_node->next()) {
const TestInfo* const test_info = test_info_node->element();
if (test_info->matches_filter()) { if (test_info->matches_filter()) {
if (!printed_test_case_name) { if (!printed_test_case_name) {
printed_test_case_name = true; printed_test_case_name = true;

View File

@ -46,7 +46,6 @@ namespace testing {
namespace { namespace {
using internal::List; using internal::List;
using internal::ListNode;
using internal::String; using internal::String;
using internal::TestProperty; using internal::TestProperty;
using internal::TestPropertyKeyIs; using internal::TestPropertyKeyIs;
@ -70,9 +69,10 @@ void ExpectKeyAndValueWereRecordedForId(const List<TestProperty>& properties,
int id, int id,
const char* suffix) { const char* suffix) {
TestPropertyKeyIs matches_key(IdToKey(id, suffix).c_str()); TestPropertyKeyIs matches_key(IdToKey(id, suffix).c_str());
const ListNode<TestProperty>* node = properties.FindIf(matches_key); const TestProperty* property = properties.FindIf(matches_key);
EXPECT_TRUE(node != NULL) << "expecting " << suffix << " node for id " << id; ASSERT_TRUE(property != NULL)
EXPECT_STREQ(IdToString(id).c_str(), node->element().value()); << "expecting " << suffix << " value for id " << id;
EXPECT_STREQ(IdToString(id).c_str(), property->value());
} }
// Calls a large number of Google Test assertions, where exactly one of them // Calls a large number of Google Test assertions, where exactly one of them

View File

@ -76,6 +76,16 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
#include <map> #include <map>
#endif #endif
// GTEST_EXPECT_DEATH_IF_SUPPORTED_(statement, regex) expands to a
// real death test if death tests are supported; otherwise it expands
// to empty.
#if GTEST_HAS_DEATH_TEST
#define GTEST_EXPECT_DEATH_IF_SUPPORTED_(statement, regex) \
EXPECT_DEATH(statement, regex)
#else
#define GTEST_EXPECT_DEATH_IF_SUPPORTED_(statement, regex)
#endif
namespace testing { namespace testing {
namespace internal { namespace internal {
const char* FormatTimeInMillisAsSeconds(TimeInMillis ms); const char* FormatTimeInMillisAsSeconds(TimeInMillis ms);
@ -448,31 +458,56 @@ TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
} }
#endif // !GTEST_WIDE_STRING_USES_UTF16_ #endif // !GTEST_WIDE_STRING_USES_UTF16_
// Tests the List template class. // Tests the List class template.
// Tests List::Clear().
TEST(ListTest, Clear) {
List<int> a;
a.PushBack(1);
a.Clear();
EXPECT_EQ(0, a.size());
a.PushBack(2);
a.PushBack(3);
a.Clear();
EXPECT_EQ(0, a.size());
}
// Tests List::PushBack().
TEST(ListTest, PushBack) {
List<char> a;
a.PushBack('a');
ASSERT_EQ(1, a.size());
EXPECT_EQ('a', a.GetElement(0));
a.PushBack('b');
ASSERT_EQ(2, a.size());
EXPECT_EQ('a', a.GetElement(0));
EXPECT_EQ('b', a.GetElement(1));
}
// Tests List::PushFront(). // Tests List::PushFront().
TEST(ListTest, PushFront) { TEST(ListTest, PushFront) {
List<int> a; List<int> a;
ASSERT_EQ(0u, a.size()); ASSERT_EQ(0, a.size());
// Calls PushFront() on an empty list. // Calls PushFront() on an empty list.
a.PushFront(1); a.PushFront(1);
ASSERT_EQ(1u, a.size()); ASSERT_EQ(1, a.size());
EXPECT_EQ(1, a.Head()->element()); EXPECT_EQ(1, a.GetElement(0));
ASSERT_EQ(a.Head(), a.Last());
// Calls PushFront() on a singleton list. // Calls PushFront() on a singleton list.
a.PushFront(2); a.PushFront(2);
ASSERT_EQ(2u, a.size()); ASSERT_EQ(2, a.size());
EXPECT_EQ(2, a.Head()->element()); EXPECT_EQ(2, a.GetElement(0));
EXPECT_EQ(1, a.Last()->element()); EXPECT_EQ(1, a.GetElement(1));
// Calls PushFront() on a list with more than one elements. // Calls PushFront() on a list with more than one elements.
a.PushFront(3); a.PushFront(3);
ASSERT_EQ(3u, a.size()); ASSERT_EQ(3, a.size());
EXPECT_EQ(3, a.Head()->element()); EXPECT_EQ(3, a.GetElement(0));
EXPECT_EQ(2, a.Head()->next()->element()); EXPECT_EQ(2, a.GetElement(1));
EXPECT_EQ(1, a.Last()->element()); EXPECT_EQ(1, a.GetElement(2));
} }
// Tests List::PopFront(). // Tests List::PopFront().
@ -497,75 +532,91 @@ TEST(ListTest, PopFront) {
// After popping the last element, the list should be empty. // After popping the last element, the list should be empty.
EXPECT_TRUE(a.PopFront(NULL)); EXPECT_TRUE(a.PopFront(NULL));
EXPECT_EQ(0u, a.size()); EXPECT_EQ(0, a.size());
} }
// Tests inserting at the beginning using List::InsertAfter(). // Tests inserting at the beginning using List::Insert().
TEST(ListTest, InsertAfterAtBeginning) { TEST(ListTest, InsertAtBeginning) {
List<int> a; List<int> a;
ASSERT_EQ(0u, a.size()); ASSERT_EQ(0, a.size());
// Inserts into an empty list. // Inserts into an empty list.
a.InsertAfter(NULL, 1); a.Insert(1, 0);
ASSERT_EQ(1u, a.size()); ASSERT_EQ(1, a.size());
EXPECT_EQ(1, a.Head()->element()); EXPECT_EQ(1, a.GetElement(0));
ASSERT_EQ(a.Head(), a.Last());
// Inserts at the beginning of a singleton list. // Inserts at the beginning of a singleton list.
a.InsertAfter(NULL, 2); a.Insert(2, 0);
ASSERT_EQ(2u, a.size()); ASSERT_EQ(2, a.size());
EXPECT_EQ(2, a.Head()->element()); EXPECT_EQ(2, a.GetElement(0));
EXPECT_EQ(1, a.Last()->element()); EXPECT_EQ(1, a.GetElement(1));
// Inserts at the beginning of a list with more than one elements. // Inserts at the beginning of a list with more than one elements.
a.InsertAfter(NULL, 3); a.Insert(3, 0);
ASSERT_EQ(3u, a.size()); ASSERT_EQ(3, a.size());
EXPECT_EQ(3, a.Head()->element()); EXPECT_EQ(3, a.GetElement(0));
EXPECT_EQ(2, a.Head()->next()->element()); EXPECT_EQ(2, a.GetElement(1));
EXPECT_EQ(1, a.Last()->element()); EXPECT_EQ(1, a.GetElement(2));
} }
// Tests inserting at a location other than the beginning using // Tests inserting at a location other than the beginning using
// List::InsertAfter(). // List::Insert().
TEST(ListTest, InsertAfterNotAtBeginning) { TEST(ListTest, InsertNotAtBeginning) {
// Prepares a singleton list. // Prepares a singleton list.
List<int> a; List<int> a;
a.PushBack(1); a.PushBack(1);
// Inserts at the end of a singleton list. // Inserts at the end of a singleton list.
a.InsertAfter(a.Last(), 2); a.Insert(2, a.size());
ASSERT_EQ(2u, a.size()); ASSERT_EQ(2, a.size());
EXPECT_EQ(1, a.Head()->element()); EXPECT_EQ(1, a.GetElement(0));
EXPECT_EQ(2, a.Last()->element()); EXPECT_EQ(2, a.GetElement(1));
// Inserts at the end of a list with more than one elements. // Inserts at the end of a list with more than one elements.
a.InsertAfter(a.Last(), 3); a.Insert(3, a.size());
ASSERT_EQ(3u, a.size()); ASSERT_EQ(3, a.size());
EXPECT_EQ(1, a.Head()->element()); EXPECT_EQ(1, a.GetElement(0));
EXPECT_EQ(2, a.Head()->next()->element()); EXPECT_EQ(2, a.GetElement(1));
EXPECT_EQ(3, a.Last()->element()); EXPECT_EQ(3, a.GetElement(2));
// Inserts in the middle of a list. // Inserts in the middle of a list.
a.InsertAfter(a.Head(), 4); a.Insert(4, 1);
ASSERT_EQ(4u, a.size()); ASSERT_EQ(4, a.size());
EXPECT_EQ(1, a.Head()->element()); EXPECT_EQ(1, a.GetElement(0));
EXPECT_EQ(4, a.Head()->next()->element()); EXPECT_EQ(4, a.GetElement(1));
EXPECT_EQ(2, a.Head()->next()->next()->element()); EXPECT_EQ(2, a.GetElement(2));
EXPECT_EQ(3, a.Last()->element()); EXPECT_EQ(3, a.GetElement(3));
}
// Tests List::GetElementOr().
TEST(ListTest, GetElementOr) {
List<char> a;
EXPECT_EQ('x', a.GetElementOr(0, 'x'));
a.PushBack('a');
a.PushBack('b');
EXPECT_EQ('a', a.GetElementOr(0, 'x'));
EXPECT_EQ('b', a.GetElementOr(1, 'x'));
EXPECT_EQ('x', a.GetElementOr(-2, 'x'));
EXPECT_EQ('x', a.GetElementOr(2, 'x'));
} }
// Tests the GetElement accessor. // Tests the GetElement accessor.
TEST(ListTest, GetElement) { TEST(ListDeathTest, GetElement) {
List<int> a; List<int> a;
a.PushBack(0); a.PushBack(0);
a.PushBack(1); a.PushBack(1);
a.PushBack(2); a.PushBack(2);
EXPECT_EQ(&(a.Head()->element()), a.GetElement(0)); EXPECT_EQ(0, a.GetElement(0));
EXPECT_EQ(&(a.Head()->next()->element()), a.GetElement(1)); EXPECT_EQ(1, a.GetElement(1));
EXPECT_EQ(&(a.Head()->next()->next()->element()), a.GetElement(2)); EXPECT_EQ(2, a.GetElement(2));
EXPECT_TRUE(a.GetElement(3) == NULL); GTEST_EXPECT_DEATH_IF_SUPPORTED_(
EXPECT_TRUE(a.GetElement(-1) == NULL); a.GetElement(3),
"Invalid list index 3: must be in range \\[0, 2\\]\\.");
GTEST_EXPECT_DEATH_IF_SUPPORTED_(
a.GetElement(-1),
"Invalid list index -1: must be in range \\[0, 2\\]\\.");
} }
// Tests the String class. // Tests the String class.
@ -1128,18 +1179,17 @@ class TestResultTest : public Test {
} }
// Helper that compares two two TestPartResults. // Helper that compares two two TestPartResults.
static void CompareTestPartResult(const TestPartResult* expected, static void CompareTestPartResult(const TestPartResult& expected,
const TestPartResult* actual) { const TestPartResult& actual) {
ASSERT_TRUE(actual != NULL); EXPECT_EQ(expected.type(), actual.type());
EXPECT_EQ(expected->type(), actual->type()); EXPECT_STREQ(expected.file_name(), actual.file_name());
EXPECT_STREQ(expected->file_name(), actual->file_name()); EXPECT_EQ(expected.line_number(), actual.line_number());
EXPECT_EQ(expected->line_number(), actual->line_number()); EXPECT_STREQ(expected.summary(), actual.summary());
EXPECT_STREQ(expected->summary(), actual->summary()); EXPECT_STREQ(expected.message(), actual.message());
EXPECT_STREQ(expected->message(), actual->message()); EXPECT_EQ(expected.passed(), actual.passed());
EXPECT_EQ(expected->passed(), actual->passed()); EXPECT_EQ(expected.failed(), actual.failed());
EXPECT_EQ(expected->failed(), actual->failed()); EXPECT_EQ(expected.nonfatally_failed(), actual.nonfatally_failed());
EXPECT_EQ(expected->nonfatally_failed(), actual->nonfatally_failed()); EXPECT_EQ(expected.fatally_failed(), actual.fatally_failed());
EXPECT_EQ(expected->fatally_failed(), actual->fatally_failed());
} }
}; };
@ -1193,11 +1243,18 @@ TEST_F(TestResultTest, Failed) {
} }
// Tests TestResult::GetTestPartResult(). // Tests TestResult::GetTestPartResult().
TEST_F(TestResultTest, GetTestPartResult) {
CompareTestPartResult(pr1, r2->GetTestPartResult(0)); typedef TestResultTest TestResultDeathTest;
CompareTestPartResult(pr2, r2->GetTestPartResult(1));
EXPECT_TRUE(r2->GetTestPartResult(2) == NULL); TEST_F(TestResultDeathTest, GetTestPartResult) {
EXPECT_TRUE(r2->GetTestPartResult(-1) == NULL); CompareTestPartResult(*pr1, r2->GetTestPartResult(0));
CompareTestPartResult(*pr2, r2->GetTestPartResult(1));
GTEST_EXPECT_DEATH_IF_SUPPORTED_(
r2->GetTestPartResult(2),
"Invalid list index 2: must be in range \\[0, 1\\]\\.");
GTEST_EXPECT_DEATH_IF_SUPPORTED_(
r2->GetTestPartResult(-1),
"Invalid list index -1: must be in range \\[0, 1\\]\\.");
} }
// Tests TestResult has no properties when none are added. // Tests TestResult has no properties when none are added.
@ -1212,9 +1269,9 @@ TEST(TestResultPropertyTest, OnePropertyFoundWhenAdded) {
TestProperty property("key_1", "1"); TestProperty property("key_1", "1");
TestResultAccessor::RecordProperty(&test_result, property); TestResultAccessor::RecordProperty(&test_result, property);
ASSERT_EQ(1, test_result.test_property_count()); ASSERT_EQ(1, test_result.test_property_count());
const TestProperty* actual_property = test_result.GetTestProperty(0); const TestProperty& actual_property = test_result.GetTestProperty(0);
EXPECT_STREQ("key_1", actual_property->key()); EXPECT_STREQ("key_1", actual_property.key());
EXPECT_STREQ("1", actual_property->value()); EXPECT_STREQ("1", actual_property.value());
} }
// Tests TestResult has multiple properties when added. // Tests TestResult has multiple properties when added.
@ -1225,13 +1282,13 @@ TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
TestResultAccessor::RecordProperty(&test_result, property_1); TestResultAccessor::RecordProperty(&test_result, property_1);
TestResultAccessor::RecordProperty(&test_result, property_2); TestResultAccessor::RecordProperty(&test_result, property_2);
ASSERT_EQ(2, test_result.test_property_count()); ASSERT_EQ(2, test_result.test_property_count());
const TestProperty* actual_property_1 = test_result.GetTestProperty(0); const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
EXPECT_STREQ("key_1", actual_property_1->key()); EXPECT_STREQ("key_1", actual_property_1.key());
EXPECT_STREQ("1", actual_property_1->value()); EXPECT_STREQ("1", actual_property_1.value());
const TestProperty* actual_property_2 = test_result.GetTestProperty(1); const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
EXPECT_STREQ("key_2", actual_property_2->key()); EXPECT_STREQ("key_2", actual_property_2.key());
EXPECT_STREQ("2", actual_property_2->value()); EXPECT_STREQ("2", actual_property_2.value());
} }
// Tests TestResult::RecordProperty() overrides values for duplicate keys. // Tests TestResult::RecordProperty() overrides values for duplicate keys.
@ -1247,17 +1304,17 @@ TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
TestResultAccessor::RecordProperty(&test_result, property_2_2); TestResultAccessor::RecordProperty(&test_result, property_2_2);
ASSERT_EQ(2, test_result.test_property_count()); ASSERT_EQ(2, test_result.test_property_count());
const TestProperty* actual_property_1 = test_result.GetTestProperty(0); const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
EXPECT_STREQ("key_1", actual_property_1->key()); EXPECT_STREQ("key_1", actual_property_1.key());
EXPECT_STREQ("12", actual_property_1->value()); EXPECT_STREQ("12", actual_property_1.value());
const TestProperty* actual_property_2 = test_result.GetTestProperty(1); const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
EXPECT_STREQ("key_2", actual_property_2->key()); EXPECT_STREQ("key_2", actual_property_2.key());
EXPECT_STREQ("22", actual_property_2->value()); EXPECT_STREQ("22", actual_property_2.value());
} }
// Tests TestResult::GetTestProperty(). // Tests TestResult::GetTestProperty().
TEST(TestResultPropertyTest, GetTestProperty) { TEST(TestResultPropertyDeathTest, GetTestProperty) {
TestResult test_result; TestResult test_result;
TestProperty property_1("key_1", "1"); TestProperty property_1("key_1", "1");
TestProperty property_2("key_2", "2"); TestProperty property_2("key_2", "2");
@ -1266,24 +1323,25 @@ TEST(TestResultPropertyTest, GetTestProperty) {
TestResultAccessor::RecordProperty(&test_result, property_2); TestResultAccessor::RecordProperty(&test_result, property_2);
TestResultAccessor::RecordProperty(&test_result, property_3); TestResultAccessor::RecordProperty(&test_result, property_3);
const TestProperty* fetched_property_1 = test_result.GetTestProperty(0); const TestProperty& fetched_property_1 = test_result.GetTestProperty(0);
const TestProperty* fetched_property_2 = test_result.GetTestProperty(1); const TestProperty& fetched_property_2 = test_result.GetTestProperty(1);
const TestProperty* fetched_property_3 = test_result.GetTestProperty(2); const TestProperty& fetched_property_3 = test_result.GetTestProperty(2);
ASSERT_TRUE(fetched_property_1 != NULL); EXPECT_STREQ("key_1", fetched_property_1.key());
EXPECT_STREQ("key_1", fetched_property_1->key()); EXPECT_STREQ("1", fetched_property_1.value());
EXPECT_STREQ("1", fetched_property_1->value());
ASSERT_TRUE(fetched_property_2 != NULL); EXPECT_STREQ("key_2", fetched_property_2.key());
EXPECT_STREQ("key_2", fetched_property_2->key()); EXPECT_STREQ("2", fetched_property_2.value());
EXPECT_STREQ("2", fetched_property_2->value());
ASSERT_TRUE(fetched_property_3 != NULL); EXPECT_STREQ("key_3", fetched_property_3.key());
EXPECT_STREQ("key_3", fetched_property_3->key()); EXPECT_STREQ("3", fetched_property_3.value());
EXPECT_STREQ("3", fetched_property_3->value());
ASSERT_TRUE(test_result.GetTestProperty(3) == NULL); GTEST_EXPECT_DEATH_IF_SUPPORTED_(
ASSERT_TRUE(test_result.GetTestProperty(-1) == NULL); test_result.GetTestProperty(3),
"Invalid list index 3: must be in range \\[0, 2\\]\\.");
GTEST_EXPECT_DEATH_IF_SUPPORTED_(
test_result.GetTestProperty(-1),
"Invalid list index -1: must be in range \\[0, 2\\]\\.");
} }
// When a property using a reserved key is supplied to this function, it tests // When a property using a reserved key is supplied to this function, it tests
@ -1548,29 +1606,26 @@ TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) {
SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "-123"); SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "-123");
EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333)); EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
} }
#endif // _WIN32_WCE #endif // _WIN32_WCE
#if GTEST_HAS_DEATH_TEST
// Tests that Int32FromEnvOrDie() aborts with an error message // Tests that Int32FromEnvOrDie() aborts with an error message
// if the variable is not an Int32. // if the variable is not an Int32.
TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) { TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) {
SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "xxx"); SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "xxx");
EXPECT_DEATH({Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123);}, GTEST_EXPECT_DEATH_IF_SUPPORTED_(
".*"); Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
".*");
} }
// Tests that Int32FromEnvOrDie() aborts with an error message // Tests that Int32FromEnvOrDie() aborts with an error message
// if the variable cannot be represnted by an Int32. // if the variable cannot be represnted by an Int32.
TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) { TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) {
SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234"); SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234");
EXPECT_DEATH({Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123);}, GTEST_EXPECT_DEATH_IF_SUPPORTED_(
".*"); Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
".*");
} }
#endif // GTEST_HAS_DEATH_TEST
// Tests that ShouldRunTestOnShard() selects all tests // Tests that ShouldRunTestOnShard() selects all tests
// where there is 1 shard. // where there is 1 shard.
TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) { TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) {
@ -1635,35 +1690,34 @@ TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
EXPECT_TRUE(ShouldShard(total_var_, index_var_, false)); EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
EXPECT_FALSE(ShouldShard(total_var_, index_var_, true)); EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
} }
#endif // _WIN32_WCE #endif // _WIN32_WCE
#if GTEST_HAS_DEATH_TEST
// Tests that we exit in error if the sharding values are not valid. // Tests that we exit in error if the sharding values are not valid.
TEST_F(ShouldShardTest, AbortsWhenShardingEnvVarsAreInvalid) {
typedef ShouldShardTest ShouldShardDeathTest;
TEST_F(ShouldShardDeathTest, AbortsWhenShardingEnvVarsAreInvalid) {
SetEnv(index_var_, "4"); SetEnv(index_var_, "4");
SetEnv(total_var_, "4"); SetEnv(total_var_, "4");
EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, GTEST_EXPECT_DEATH_IF_SUPPORTED_(ShouldShard(total_var_, index_var_, false),
".*"); ".*");
SetEnv(index_var_, "4"); SetEnv(index_var_, "4");
SetEnv(total_var_, "-2"); SetEnv(total_var_, "-2");
EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, GTEST_EXPECT_DEATH_IF_SUPPORTED_(ShouldShard(total_var_, index_var_, false),
".*"); ".*");
SetEnv(index_var_, "5"); SetEnv(index_var_, "5");
SetEnv(total_var_, ""); SetEnv(total_var_, "");
EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, GTEST_EXPECT_DEATH_IF_SUPPORTED_(ShouldShard(total_var_, index_var_, false),
".*"); ".*");
SetEnv(index_var_, ""); SetEnv(index_var_, "");
SetEnv(total_var_, "5"); SetEnv(total_var_, "5");
EXPECT_DEATH({ShouldShard(total_var_, index_var_, false);}, GTEST_EXPECT_DEATH_IF_SUPPORTED_(ShouldShard(total_var_, index_var_, false),
".*"); ".*");
} }
#endif // GTEST_HAS_DEATH_TEST
// Tests that ShouldRunTestOnShard is a partition when 5 // Tests that ShouldRunTestOnShard is a partition when 5
// shards are used. // shards are used.
TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereAreFiveShards) { TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereAreFiveShards) {
@ -3624,31 +3678,31 @@ namespace testing {
TEST(SuccessfulAssertionTest, SUCCEED) { TEST(SuccessfulAssertionTest, SUCCEED) {
SUCCEED(); SUCCEED();
SUCCEED() << "OK"; SUCCEED() << "OK";
EXPECT_EQ(2u, GetSuccessfulPartCount()); EXPECT_EQ(2, GetSuccessfulPartCount());
} }
// Tests that Google Test doesn't track successful EXPECT_*. // Tests that Google Test doesn't track successful EXPECT_*.
TEST(SuccessfulAssertionTest, EXPECT) { TEST(SuccessfulAssertionTest, EXPECT) {
EXPECT_TRUE(true); EXPECT_TRUE(true);
EXPECT_EQ(0u, GetSuccessfulPartCount()); EXPECT_EQ(0, GetSuccessfulPartCount());
} }
// Tests that Google Test doesn't track successful EXPECT_STR*. // Tests that Google Test doesn't track successful EXPECT_STR*.
TEST(SuccessfulAssertionTest, EXPECT_STR) { TEST(SuccessfulAssertionTest, EXPECT_STR) {
EXPECT_STREQ("", ""); EXPECT_STREQ("", "");
EXPECT_EQ(0u, GetSuccessfulPartCount()); EXPECT_EQ(0, GetSuccessfulPartCount());
} }
// Tests that Google Test doesn't track successful ASSERT_*. // Tests that Google Test doesn't track successful ASSERT_*.
TEST(SuccessfulAssertionTest, ASSERT) { TEST(SuccessfulAssertionTest, ASSERT) {
ASSERT_TRUE(true); ASSERT_TRUE(true);
EXPECT_EQ(0u, GetSuccessfulPartCount()); EXPECT_EQ(0, GetSuccessfulPartCount());
} }
// Tests that Google Test doesn't track successful ASSERT_STR*. // Tests that Google Test doesn't track successful ASSERT_STR*.
TEST(SuccessfulAssertionTest, ASSERT_STR) { TEST(SuccessfulAssertionTest, ASSERT_STR) {
ASSERT_STREQ("", ""); ASSERT_STREQ("", "");
EXPECT_EQ(0u, GetSuccessfulPartCount()); EXPECT_EQ(0, GetSuccessfulPartCount());
} }
} // namespace testing } // namespace testing