trying to match field of derived class pointer

2,574 views
Skip to first unread message

jcsneaker

unread,
Mar 30, 2010, 11:14:03 AM3/30/10
to Google C++ Mocking Framework
hi,

i have a setup like this:
class Base { ... };
class Derived : public Base {
bool variable; // only defined in Derived not in Base
};

class MockFoo : public Foo {
public:
MOCK_METHOD1(DoThis, void(Base* base));
};

What I want to do is this:
EXPECT_CALL(foo, DoThis(Field(&Derived::variable, true));

ie. the function is called with a (Base*) which is actually a
(Derived*).
Of this derived class i wish to match a field.

I have tried all sorts of combinations of pointee and
matchercast<Derived*>() without success.
I get errors like :
(DebugCommand is Derived From AbstractCommand and has fieldname
"onoff" of type bool
In function 'void testing::internal::ExplainMatchResultTo(const
testing::internal::FieldMatcher<Class, FieldType>&, const T&,
std::ostream*) [with Class = DebugCommand, FieldType = bool, T =
AbstractCommand*]':
../gmock-1.4.0/include/gmock/gmock-matchers.h:282: instantiated from
'void
testing::PolymorphicMatcher<Impl>::MonomorphicImpl<T>::ExplainMatchResultTo(T,
std::ostream*) const [with T = AbstractCommand*, Impl =
testing::internal::FieldMatcher<DebugCommand, bool>]'
DBUSCommunicator_unittest.cc:227: instantiated from here
../gmock-1.4.0/include/gmock/gmock-matchers.h:1555: error: invalid
conversion from 'AbstractCommand* const' to 'const DebugCommand*'
../gmock-1.4.0/include/gmock/gmock-matchers.h:1555: error:
initializing argument 2 of 'void
testing::internal::FieldMatcher<Class,
FieldType>::ExplainMatchResultTo(testing::internal::true_type, const
Class*, std::ostream*) const [with Class = DebugCommand, FieldType =
bool]'
make: *** [DBUSCommunicator_unittest.o] Fehler 1


Should EXPECT_CALL(foo, DoThis(Field(&Derived::variable, true)); not
work??
Documentaion says Field can also take pointers automatically.

Somebody have some ideas? Seems to be a const issue, but i dont
understand it fully.

Thanks,
Jonathan from Germany

Vlad Losev

unread,
Mar 30, 2010, 7:11:10 PM3/30/10
to Google C++ Mocking Framework
Hi Jonathan,

Google Mock's matchers are designed to perform only safe type casts. The problem is you are trying to make something very unsafe. What if the Base pointer passed into DoThis does not actually point to Derived? A handwritten code would need a check that employs dynamic_cast to work correctly, and Google Mock's matchers will not work at all.

What you can do is to write a custom matcher that will check that the passed argument is of the correct type and only then use it as such:

MATCHER(IsDerivedAndVariableMatches, value, "is Derived and has variable equal to %(value)s") {
  if (arg ==NULL)
    return false;
  Derived* derived = dynamic_cast<Derived*>(arg);
  if (derived == NULL) {
    *result_listener << "which doesn't point to Derived";
    return false;
  }
  *result_listener << "which has Derived::variable field equal to " << derived->variable;
  return derived->variable == value;
}


Thanks,
Jonathan from Germany

To unsubscribe from this group, send email to googlemock+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.

HTH,
Vlad

Istrate Roxana

unread,
Jul 25, 2014, 11:36:04 AM7/25/14
to googl...@googlegroups.com
Hello, 

I have the same problem like Jonathan. I will post my code here:

class Packet
{
public:
    Packet(){}
    virtual ~Packet(){}
};

class MyPacket 
: public Packet
{
int ql;

public:

int get_QL();

}

MATCHER_P(IsDerivedAndVariableMatches, value, ""){
if (arg == NULL)
return false;
MyPacket *derived = dynamic_cast<MyPacket*>(arg);
if (derived == NULL){
*result_listener << "which doesn't point to MyPacket";
return false;
}
*result_listener << "which has MyPacket::variable field equal to" << derived->get_QL();
return derived->get_QL() == value;
}

EXPECT_CALL(ms, Write(AllOf(Property(&Packet::get_QL, IsDerivedAndVariableMatches(0))))).Times(1).WillOnce(Return(true));

and I get this error:

error: 'get_QL' is not a member of 'Packet

and if I modify like this:

EXPECT_CALL(ms, Write(AllOf(Property(&MyPacket::get_QL, IsDerivedAndVariableMatches(0))))).Times(1).WillOnce(Return(true));

I get this error:

invalid conversion from 'Packet*' to 'const MyPacket*'

How can I fix this?

I mention that if the code is like this:

EXPECT_CALL(ms, Write(AllOf(Property(&MyPacket::get_QL,Eq(0))))).Times(1).WillOnce(Return(true));

and I compile with -fpermissive the code woks fine, but i don't want to use the flag. 

Vlad Losev

unread,
Jul 25, 2014, 8:03:29 PM7/25/14
to Google C++ Mocking Framework
Because IsDerivedAndVariableMatches already reaches into MyPacket to call get_QL(), the correct way to write your expectation using it will be


EXPECT_CALL(ms,
            Write(IsDerivedAndVariableMatches(0)))
    .WillOnce(Return(true));

An alternative way of writing this without using custom matchers is to use the new standard matcher WhenDynamicCastTo:

EXPECT_CALL(
    ms,
    Write(WhenDynamicCastTo<MyPacket*>(
        Property(&MyPacket::get_QL, 0)))
    .WillOnce(Return(true));


You are right not to want that because the resulting code is incorrect.  If Write is called with a Packet* object that is not of actual type MyPacket, the framework will try to static_cast it to MyPacket* and the following attempts to dereference the result will constitute undefined behavior.

--

---
You received this message because you are subscribed to the Google Groups "Google C++ Mocking Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to googlemock+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/googlemock/900dd3dc-8cdc-40cd-ab22-5ea0806fe65f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages