Contents
This package wraps Mock Objects for a service server, a message subscriber and a actionlib server.
Creating a Mock Object
First include the code dependencies and add to your code the following include files
#include "ros/ros.h" #include "gtest/gtest.h" #include "mock_objects/MockSubscriber.h"
To create a mock subscriber
typedef controllersAndSensors_communications::irMsg ir; MockSubscriber<ir> irSubscriber;
Creating a mock action server can be done as in this example:
#include "ros/ros.h"
#include "mock_objects/MockActionServer.h"
#include "RoboticArm_communications/moveArmAction.h"
MOCK_ACTION_SERVER(hello,RoboticArm_communications::moveArm)
int main() {
MockhelloActionServer a("test");
}
Range Checks using mock objects
You can use the mock objects for performing range checks, using the build in google mock functions. For a message with the definition
Header header int32[5] distance
the following range check can be defined:
EXPECT_CALL(irSubscriber, subscriberActualCallback( Pointee(Field(&ir::distance, ElementsAre( AnyOf(IsBetween(0, 800), Eq(-1)), AnyOf(IsBetween(0, 300), Eq(-1)), AnyOf(IsBetween(0, 300), Eq(-1)), AnyOf(IsBetween(0, 800), Eq(-1)), AnyOf(IsBetween(40, 300), Eq(-1)))) ))).Times(AtLeast(0));
where the IsBetween is a matcher defined as follows:
MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is")
+ " between " + PrintToString(a) + " and " + PrintToString(b)) {
return a <=arg;
}Note that you need to add the following lines too
using ::testing::AtLeast; using ::testing::Eq; using ::testing::AllOf; using ::testing::Field; using ::testing::Pointee; using ::testing::PrintToString; using ::testing::ElementsAre; using ::testing::Matcher; using ::testing::AnyOf;
Complex Logical Rules
Combining the Google Mock AnyOf and AllOf matchers can provide more complex rules for range checks. For example:
EXPECT_CALL(soundExistenceSubscriber, subscriberActualCallback(
AllOf(
AnyOf(
Pointee(Field(&existenceMsg::soundExists, Eq(0))),
Pointee(Field(&existenceMsg::soundExists, Eq(1)))
),
Pointee(Field(&existenceMsg::certainty, IsBetween(0,1)))
))).Times(AtLeast(0)); and a simple or-like statement
EXPECT_CALL(lineColorSubscriber, subscriberActualCallback(
AnyOf(
AllOf(
Pointee(Field(&lineMsg::orientation, Eq(1))),
Pointee(Field(&lineMsg::fromAngle, IsBetween(-XCAM,XCAM))),
Pointee(Field(&lineMsg::toAngle, IsBetween(-XCAM, XCAM))),
Pointee(Field(&lineMsg::color, IsBetween(1,4)))),
AllOf(
Pointee(Field(&lineMsg::orientation, Eq(2))),
Pointee(Field(&lineMsg::fromAngle, IsBetween(-YCAM, YCAM))),
Pointee(Field(&lineMsg::toAngle, IsBetween(-YCAM, YCAM))),
Pointee(Field(&lineMsg::color, IsBetween(1,4))))
))).Times(AtLeast(0));
Define New Matchers
You can define new matchers to simplify rules. For example, checking a message that has x,y,z that all messages fall into a sphere of a specific distance, we first define a matcher:
MATCHER_P(DistanceIsLess, distance, "") {
return arg.x*arg.x+arg.y*arg.y+arg.z*arg.z < distance * distance;
}and then use it.
TF matcher
A matcher for the tf is as follows
MATCHER_P8(tfLimit, frame, childFrame, minX, maxX, minY, maxY, minZ, maxZ, std::string(negation ? "isn't" : "is")
+ " between " + PrintToString(minX) + " and " + PrintToString(maxX)) {
bool xInLimit = arg.transform.translation.x >= minX &&
arg.transform.translation.x <= maxX;
bool yInLimit = arg.transform.translation.y >= minY &&
arg.transform.translation.y <= maxY;
bool zInLimit = arg.transform.translation.z >= minZ &&
arg.transform.translation.y <= maxZ;
bool correctFrames = (frame == arg.header.frame_id) &&
(childFrame == arg.child_frame_id);
if (correctFrames)
return xInLimit && yInLimit && zInLimit;
return 1;
}
More Examples
You can find more examples in the RangeTests package and at the googlemock documentation.