Comparison of arrays in google test?
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.
How does gtest compare the values in two arrays?
You don't need to add a dependency on googlemock if you don't want, you could write your own simple function that returns a testing::AssertionResult
, e.g.
template<typename T, size_t size>
::testing::AssertionResult ArraysMatch(const T (&expected)[size],
const T (&actual)[size]){
for (size_t i(0); i < size; ++i){
if (expected[i] != actual[i]){
return ::testing::AssertionFailure() << "array[" << i
<< "] (" << actual[i] << ") != expected[" << i
<< "] (" << expected[i] << ")";
}
}
return ::testing::AssertionSuccess();
}
Then in your test, call:
EXPECT_TRUE(ArraysMatch(two_sorted, two));
Google test compare pointer-arrays' content
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
. Yourexpected_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();
}
Compare containers with GoogleTest
You're just missing gtest's testing
namespace qualifier:
EXPECT_THAT(test1, ::testing::ContainerEq(test2));
Google Mock matching an array
First of all, I did not reproduce your problem. The following example compiles and the test passes:
class ServerFake {
public:
MOCK_METHOD2(sendInternal, void(uint8_t data[], uint8_t size));
};
// If only possible, I recommend you to use std::vector instead of raw array
class ServerFake2 {
public:
MOCK_METHOD1(sendInternal, void(std::vector<uint8_t> data));
};
MATCHER_P2(HasBytes, bytes, size, "") {
// unnecessary assignment, I think ...
uint8_t * dataToCheck = arg;
bool isMatch = (memcmp(dataToCheck, bytes, size) == 0);
return isMatch;
}
using ::testing::ElementsAre;
TEST(xxx, yyy) {
ServerFake* serverFake = new ServerFake;
ServerFake2* serverFake2 = new ServerFake2;
uint8_t expectedMessageData[3] = { 0x08, 0xda, 0xff };
std::vector<uint8_t> expectedMessageData2({ 0x08, 0xda, 0xff });
EXPECT_CALL(*serverFake, sendInternal(HasBytes(expectedMessageData, 3), 3)).Times(1);
// the code below compiles and passes as well! However, I didn't check why;
// EXPECT_CALL(*serverFake, sendInternal(testing::_,3))
// .With(testing::Args<0, 1>(ElementsAre(0x08, 0xda, 0xff)))
// .Times(1);
serverFake->sendInternal(expectedMessageData, 3);
// much better, do like this!
EXPECT_CALL(*serverFake2, sendInternal(ElementsAre(0x08, 0xda, 0xff))).Times(1);
serverFake2->sendInternal(expectedMessageData2);
delete serverFake;
delete serverFake2;
}
Second, ElementsAre
officially does not support C-style arrays, according to this topic. If you really cannot change your method signature, and you really wish to use ElementsAre
on your raw array, you can use the hack proposed in that topic. Cheers.
Comparing two 2D arrays with different length for matches
I would suggest the following changes:
(1) As you are using data from single columns, you don't need the variables y
and j
.
sheetdata[x][0]
will be the value of the string in the xth row of the array.
And sheet1data[i][0]
will be the value of the string in the ith row of the array.
(2) Arrays are zero-based, i.e. the first "row" in the array is 0. Where as the first row on the sheet is 1.
So when writing to the sheet for the xth row in the array, you need to write to the x+1 th row on the sheet.
Here is what the for
loops will look like with these changes:
for (var x = 0; x < sheetdata.length; x++) {
for(var i = 0; i < sheet1data.length; i++){
if (sheetdata[x][0] == sheet1data[i][0]){
sheet1.getRange(x + 1, 2).setValue("Already in other Spreadsheet");
match.push(sheetdata[x][0]);
};
};
};
And as Tanaike-san said, lastRow1
should be used in calculating range1
and not lastRow
:
var range1 = sheet1.getRange(1, 2, lastrow1, 1);
Fastest method to compare two arrays for find equal value on Google app script
Thank you @sandy-good !,
If it is an 1D array we can use indexOf() method.
for(var line in firstArray)
{
var isMatched = secondArray.indexOf(firstArray[line]);
if (isMatched !== -1)
{
var matchedValFromArray2 = secondArray[isMatched]
};
}
If you want to compare 2D array (or two rows of a spreadsheet), you can use .join()
method.
for(var i in firstArray)
{
var duplicate = false;
for(var j in secondArray)
{
if(firstArray[i].join() == secondArray[j].join())
{
var matchedValFromArray2 = firstArray[i];
break;
}
}
}
Compare Eigen matrices in Google Test or Google Mock
Why not use the isApprox
or isMuchSmallerThan
member functions of Eigen Matrix types?
The documentation of these above functions are available here
So for most cases ASSERT_TRUE(C_actual.isApprox(C_expect));
is what you need. You can also provide a precision parameter as the second arguement to isApprox.
Related Topics
Error: 'Null' Was Not Declared in This Scope
Calling Constructors in C++ Without New
Passing Std::String by Value or Reference
Is There Any 'Out-Of-The-Box' 2D/3D Plotting Library for C++
Why Simple Console App Runs But Dialog Based Does Not Run in Win Ce 6.0
Problems with C++ Set Container
What Happens When an Exception Goes Unhandled in a Multithreaded C++11 Program
Special Characters in Visual Studio 2019 C++ Project and Executing Cmd Commands with Them
#Define Sqr(X) X*X. Unexpected Answer
Mixing Ifstream Getline and >>
Skipping Expected Characters Like Scanf() with Cin
Different Precision in C++ and Fortran
Receiving Only Necessary Data with C++ Socket
How to Make My Program in Qt Continually Send a String to My Arduino