I had the exact same question, so I wrote a couple of macros that do comparisons between two generic containers. It's extensible to ANY container that has const_iterator, begin, and end. If it fails, it will display a verbose message of where the array went wrong and will do so for every element that fails; it will make sure they're the same length; and the location in your code that it reports as failing is the same line where you call EXPECT_ITERABLE_EQ( std::vector< double >, a, b).
//! Using the google test framework, check all elements of two containers
#define EXPECT_ITERABLE_BASE( PREDICATE, REFTYPE, TARTYPE, ref, target) \
{ \
const REFTYPE& ref_(ref); \
const TARTYPE& target_(target); \
REFTYPE::const_iterator refIter = ref_.begin(); \
TARTYPE::const_iterator tarIter = target_.begin(); \
unsigned int i = 0; \
while(refIter != ref_.end()) { \
if ( tarIter == target_.end() ) { \
ADD_FAILURE() << #target " has a smaller length than " #ref ; \
break; \
} \
PREDICATE(* refIter, * tarIter) \
<< "Containers " #ref " (refIter) and " #target " (tarIter)" \
" differ at index " << i; \
++refIter; ++tarIter; ++i; \
} \
EXPECT_TRUE( tarIter == target_.end() ) \
<< #ref " has a smaller length than " #target ; \
}
//! Check that all elements of two same-type containers are equal
#define EXPECT_ITERABLE_EQ( TYPE, ref, target) \
EXPECT_ITERABLE_BASE( EXPECT_EQ, TYPE, TYPE, ref, target )
//! Check that all elements of two different-type containers are equal
#define EXPECT_ITERABLE_EQ2( REFTYPE, TARTYPE, ref, target) \
EXPECT_ITERABLE_BASE( EXPECT_EQ, REFTYPE, TARTYPE, ref, target )
//! Check that all elements of two same-type containers of doubles are equal
#define EXPECT_ITERABLE_DOUBLE_EQ( TYPE, ref, target) \
EXPECT_ITERABLE_BASE( EXPECT_DOUBLE_EQ, TYPE, TYPE, ref, target )
Hope this works for you (and that you actually check this answer two months after your question was submitted).
I would really suggest looking at Google C++ Mocking Framework. Even if you don't want to mock anything, it allows you to write rather complicated assertions with ease.
For example
//checks that vector v is {5, 10, 15}
ASSERT_THAT(v, ElementsAre(5, 10, 15));
//checks that map m only have elements 1 => 10, 2 => 20
ASSERT_THAT(m, ElementsAre(Pair(1, 10), Pair(2, 20)));
//checks that in vector v all the elements are greater than 10 and less than 20
ASSERT_THAT(v, Each(AllOf(Gt(10), Lt(20))));
//checks that vector v consist of
// 5, number greater than 10, anything.
ASSERT_THAT(v, ElementsAre(5, Gt(10), _));
There's plenty of matchers for every possible situations, and you can combine them to achieve almost anything.
Did I tell you that ElementsAre needs only iterators and size() method on a class to work? So it not only works with any container from STL but with custom containers also.
Google Mock claims to be almost as portable as Google Test and frankly I don't see why you wouldn't use it. It is just purely awesome.
I ran into a similar problem with comparing arrays in google test.
Since I needed comparison with basic void* and char* (for low-level code testing), I don't think either Google Mock (which I'm also using in the project) or Seth's great macro could help me in the particular situation. I wrote the following macro:
Tobias in the comments suggested casting void* to char* and using EXPECT_STREQ, a macro I somehow missed before - which looks like a better alternative.
Below is an assertion I wrote to compare [fragments of] two floating point arrays:
/* See
http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
for thorough information about comparing floating point values.
For this particular application we know that the value range is -1 to 1 (audio signal),
so we can compare to absolute delta of 1/2^22 which is the smallest representable value in
a 22-bit recording.
*/
const float FLOAT_INEQUALITY_TOLERANCE = float(1.0 / (1 << 22));
template <class T>
::testing::AssertionResult AreFloatingPointArraysEqual(
const T* const expected,
const T* const actual,
unsigned long length)
{
::testing::AssertionResult result = ::testing::AssertionFailure();
int errorsFound = 0;
const char* separator = " ";
for (unsigned long index = 0; index < length; index++)
{
if (fabs(expected[index] - actual[index]) > FLOAT_INEQUALITY_TOLERANCE)
{
if (errorsFound == 0)
{
result << "Differences found:";
}
if (errorsFound < 3)
{
result << separator
<< expected[index] << " != " << actual[index]
<< " @ " << index;
separator = ", ";
}
errorsFound++;
}
}
if (errorsFound > 0)
{
result << separator << errorsFound << " differences in total";
return result;
}
return ::testing::AssertionSuccess();
}
Usage within the Google Testing Framework is this:
I spent far too long trying to piece this together. Thanks to this StackOverflow post for the reminder on std::vector iterator initialization. Note that this method will copy the buffer array elements into the std::vector before the comparison.
I used a classic loop through all elements. You can use SCOPED_TRACE to read out in which iteration the array elements differ. This provides you with additional information compared to some other approaches and is easy to read.
for (int idx=0; idx<ui16DataSize; idx++)
{
SCOPED_TRACE(idx); //write to the console in which iteration the error occurred
ASSERT_EQ(array1[idx],array2[idx]);
}
ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
for (int i = 0; i < x.size(); ++i) {
EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}
///
/// \brief operator << print a vector in a list-initialization friendly format
/// \param out
/// \param point
/// \return
///
template <typename T>
std::ostream &operator<<(std::ostream &out, std::vector<T> const &vector)
{
out << "{";
if (!vector.empty())
{
out << vector[0];
}
for (size_t i = 1; i < vector.size(); i++)
{
out << ", " << vector[i];
}
out << "}";
return out;
}
It's very convenient also to create test cases from live data, since you just need to log the data and then use it to initialize your test array.