mimre
mimre

Reputation: 92

Google test compare pointer-arrays' content

I'm new to google test and any of the methods I've found haven't worked.

Let's assume I have an array, and then a function that returns me a pointer to a new array and I wanna compare if both of those arrays contain the same elements.

Example:

int foo[] {1,2,3};
int* expected result = foo;
int* result = bar(foo);

//comparison
EXPECT_THAT(foo, testing::UnorderedElementsAreArray(result, 3));
//other way
EXPECT_THAT(foo, testing::ContainerEq(result));

Neither of those two way (and similar tries worked).

I want to check if both arrays contain the same elements, regardless of order.

I've tried the methods in Comparison of arrays in google test? but none of them worked.

Further is "ElementsAreArray" the right comparator?

Thanks for any help.

Upvotes: 4

Views: 8034

Answers (1)

Mike Kinghan
Mike Kinghan

Reputation: 61575

The gtest matchers that you are attempting to use, testing::UnorderedElementsAreArray and testing::ContainerEq, are applicable only to objects that are STL-style containers. See the documentation.

Your foo is a C-style array of int. Your expected_result and result are pointers to int. None of these is an STL-style container, and the pointers are not containers in any sense.

The question you want to test is whether the N integers beginning at expected_result are any permutation of the N integers beginning at result, where N is the number of elements in the array foo.

The only way to test that question with a single EXPECT... call is to expect a true result when you call some function that determines exactly that question with arguments result and expected_result and returns a boolean verdict (or something convertible to a boolean verdict).

The C++ Standard library (C++11 or later) provides a generic function for just such a purpose: std::is_permutation, which you would apply as illustrated:

#include <gtest/gtest.h>
#include <algorithm>

int * reverse(int in[], std::size_t len)
{
    int * permute = new int[len];
    std::reverse_copy(in,in + len,permute);
    return permute;
}

TEST(reverse,is_correct)
{
    int foo[] {1,2,3};
    int* expected_result = foo;
    std::size_t len = sizeof(foo)/sizeof(foo[0]);
    int* result = reverse(foo,len);
    EXPECT_TRUE(std::is_permutation(result,result + len,expected_result));
    delete [] result;
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

Output:

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from reverse
[ RUN      ] reverse.is_correct
[       OK ] reverse.is_correct (0 sec)
[----------] 1 test from reverse (0 sec total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[  PASSED  ] 1 test.

Note that the use of C-style arrays obliges you manage heap memory by hand:

    int * permute = new int[len];
    ...
    ...
    delete [] result

which in C++ is a gratuitous invitation to heap-leak or heap-corruption bugs. For fixed size arrays, use std::array. For dynamically sized arrays, use std::vector. This is better:

#include <gtest/gtest.h>
#include <algorithm>
#include <array>

template<std::size_t N>
std::array<int,N> reverse(std::array<int,N> const & in)
{
    std::array<int,N> permute;
    std::reverse_copy(in.begin(),in.end(),permute.begin());
    return permute;
}

TEST(reverse,is_correct)
{
    std::array<int,3> foo {1,2,3};
    auto result = reverse(foo);
    EXPECT_TRUE(std::is_permutation(result.begin(),result.end(),foo.begin()));
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

And, since std::array and std::vector are STL-style containers, your orginal attempt would have worked had you used either one:

#include <gmock/gmock.h>
#include <algorithm>
#include <array>

template<std::size_t N>
std::array<int,N> reverse(std::array<int,N> const & in)
{
    std::array<int,N> permute;
    std::reverse_copy(in.begin(),in.end(),permute.begin());
    return permute;
}

TEST(reverse,is_correct)
{
    std::array<int,3> foo {1,2,3};
    auto result = reverse(foo);
    EXPECT_THAT(foo,testing::UnorderedElementsAreArray(result));
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

Upvotes: 3

Related Questions