Pointee and SafeMatcherCast matchers and void* pointers

3,644 views
Skip to first unread message

soeren...@gmail.com

unread,
Sep 5, 2011, 6:11:16 AM9/5/11
to Google C++ Mocking Framework
Hi,

I have got a problem with specifying expectations on a method taking a
void* argument:

class Foo {
MOCK_METHOD2(send, void(const void* buffer, size_t size));
}

What I would like to assert is that send(...) is called with a buffer
(1) that points to some uint32_t that takes some specific (integer)
value. I tried doing so like this:

const uint32_t expectedValue=123;

EXPECT_CALL(mock, send(SafeMatcherCast<const
uint32_t*>(Pointee(expectedFileNameLength)),Eq(sizeof(uint32_t))).Times(1);

There's apparently some (confusing) problem with the cast - the
compiler reports:

cannot convert parameter 1 from 'testing::Matcher<T>' to 'const
testing::Matcher<T> &'

with

[

T=const uint32_t *

]

and

[

T=const void *

]

Reason: cannot convert from 'testing::Matcher<T>' to 'const
testing::Matcher<T>'

with

[

T=const uint32_t *

]

and

[

T=const void *

]

No user-defined-conversion operator available that can perform
this conversion, or the operator cannot be called.


Swapping the order of the Pointee and SafeMatcherCast matchers (and
applying the latter on an uint32_t) will obviously not work. However,
I don't really see the problem of copying and casting a void* to a
uint32_t*.

Any ideas? Thanks heaps,
Sören

Vlad Losev

unread,
Sep 5, 2011, 2:41:24 PM9/5/11
to Google C++ Mocking Framework
SafeMatcherCast will not work for you as const void* cannot be implicitly converted to const uint32_t* - check http://code.google.com/p/googlemock/wiki/CookBook#Casting_Matchers for details. You can try MatcherCast<T>(), though.

HTH,
Vlad 

soeren...@gmail.com

unread,
Sep 6, 2011, 3:42:28 AM9/6/11
to Google C++ Mocking Framework
Thanks, Vlad - I overlooked MatcherCast in the first place. However,
using MatcherCast<const uint32_t*>(Pointee(EXPECTED_INTEGER)) is to no
avail either. Specifically, my matchers are nested like so:

EXPECT_CALL(backupDestination, send(MatcherCast<const
uint32_t*>(Pointee(Eq(EXPECTED_INTEGER))),
Eq(sizeof(uint32_t)))).Times(1);

But still, the compiler (MSVC) reports this issue:

cannot convert parameter 1 from 'testing::Matcher<T>' to 'const
testing::Matcher<T> &'

where the Ts are const uint32_t* and const void*, respectively.

From the documentation, I would have expected MatcherCast to behave
like static_cast, such that there should not be any issues casting the
void pointer to the uint32_t pointer. Also, I have used the
Truly(someFunction) workaround from the GMock cook book where
"someFunction" implements the predicate that checks for the void*
argument ("buffer") to point to an uint32_t having the expected value
(naturally using static_cast) like so:

bool someFunction(const void* buffer) {
return (buffer != NULL && EXPECTED_INTEGER == *(static_cast<const
uint32_t*>(buffer)));
}

This works just fine.

Any thoughts?

Thanks,
Sören

On 5 Sep., 20:41, Vlad Losev <v...@losev.com> wrote:
> SafeMatcherCast will not work for you as const void* cannot be implicitly
> converted to const uint32_t* - checkhttp://code.google.com/p/googlemock/wiki/CookBook#Casting_Matchersfor
> details. You can try MatcherCast<T>(), though.
>
> HTH,
> Vlad
>
> On Mon, Sep 5, 2011 at 3:11 AM, Soeren.Ba...@googlemail.com <

Vlad Losev

unread,
Sep 6, 2011, 2:47:33 PM9/6/11
to soeren...@gmail.com, Google C++ Mocking Framework
Sören -

I missed the fact that you are converting your matcher to Matcher<const unit32_t*>. You see, matcher conversions usually have to go in the direction opposite of type conversions. It's a little bit unintuitive, but perfectly logical when you think about it. In your case, Pointee(Eq(EXPECTED_INTEGER)) yields a Matcher<uint32_t> (actually, not exactly that type but close enough for the purposes of  this discussion). You have to explicitly convert to Matcher<const void*> in order to be able to match const void* pointers. The error you see is the result of the compiler trying -- and failing to perform such unsafe conversion implicitly. So your expectation might look like this:

EXPECT_CALL(
    backupDestination,
    send(MatcherCast<const void*>(Pointee(Eq(EXPECTED_INTEGER))),
            Eq(sizeof(uint32_t)))).Times(1);

But you will see the error message about an attempt to dereference void* if you try to compile the statement above.  This is due to the implementation details of Pointee, which attempts to dereference the argument passed to it (const void*) before passing it to Eq. To avoid this, you have to make sure that Pointee sees a const uint32_t* argument. You do that by casting it to Matcher<const uint32_t*>. Best to do it with the preferred SafeMatcherCast. Here is the final code that should work for you:

EXPECT_CALL(
    backupDestination,
    send(MatcherCast<const void*>(SafeMatcherCast<const uint32_t*>(
                Pointee(Eq(EXPECTED_INTEGER)))),
            Eq(sizeof(uint32_t)))).Times(1);

HTH,
Vlad
Reply all
Reply to author
Forward
0 new messages