How do I use mocks to test the content of a pointer parameter?

4,119 views
Skip to first unread message

William Ivory

unread,
Sep 9, 2014, 6:57:07 AM9/9/14
to cppu...@googlegroups.com
Hi,

I'm hoping I'm missing something trivial here, but I can't work out how to use mocks to test the contents of a parameter passed as a pointer.  I don't care about the address - it may be malloced on the fly and tricky to actually determine the address for the expect part of the mock - but I do care about the value contained in it.

As an example, my code calls a function with this prototype:

void *my_arg_create (my_arg_t *arg, int tag, const void *pval)

Depending on the type of 'tag', 'pval' may be an integer, a pointer, or a char * for example.

My mocks at present look like this (expect is in C++, actual in C):

    mock().expectOneCall("my_cli_arg_create")
    .withIntParameter("tag", SISF_TAG_BT_CURR_DYN)
    .withPointerParameter("pval", (void *)&test_value)
    .andReturnValue(NULL);

    mock_c()->actualCall("my_cli_arg_create")
    ->withIntParameters("tag", tag)
    ->withPointerParameters("pval", (void *)pval)
    ->returnValue().value.pointerValue;

I don't actually want to check pval / &test_value here as they are different.  What I want to do is to be able to compare *pval (demuxed by the type of 'tag') and compare with the expected value (test_value).  So, first I need to be able to prevent the pointer comparison, and secondly I need access to 'test_value' within the mock function, so I can compare test_value to *pval.

How can I achieve this?

Thanks,

William



James Grenning

unread,
Sep 9, 2014, 7:32:51 AM9/9/14
to cppu...@googlegroups.com
Hi William

You could use some conditional logic in the mock stub function like
this:value;

if (tag == ITS_A_STRING)
mock_c()->actualCall("my_cli_arg_create")
->withIntParameters("tag", tag)
->withStringParameters("pval", pval)
->returnValue().value.pointerValue;
else if (tag == ITS_A_POINTER)
mock_c()->actualCall("my_cli_arg_create")
->withIntParameters("tag", tag)
->withPointerParameters("pval", pval)
->returnValue().value.pointerValue;
else if (tag == ITS_AN_INT)
mock_c()->actualCall("my_cli_arg_create")
->withIntParameters("tag", tag)
->withIntParameters("pval", pval)
->returnValue().value.pointerValue;

I'm not sure i this will work, but it might.

James

--------------------------------------------------------------------------------------------
James Grenning Author of TDD for Embedded C
www.wingman-sw.com http://pragprog.com/titles/jgade/
www.wingman-sw.com/blog
www.twitter.com/jwgrenning
> --
> You received this message because you are subscribed to the Google
> Groups "cpputest" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to cpputest+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

William Ivory

unread,
Sep 9, 2014, 7:57:12 AM9/9/14
to cppu...@googlegroups.com
Hi James,

That won't work as my UUT passes in '&pval' as type (void *).  The code below will compare pval cast to an int, instead of *pval.  I wondered if I could use a custom comparator instead, but I'm struggling to get it to compile - showing my lack of C++ experience here as I tried to follow the example on cpputest.org:

class uintPtrComparator : public MockNamedValueComparator
{
public:
    virtual bool isEqual(void* object1, void* object2)
    {
        return *(unsigned int *)object1 == *(unsigned int *)object2;
    }
    virtual SimpleString valueToString(void* object)
    {
        return StringFrom(object);
    }
};

TEST_GROUP(MyTestGroup)
{

    void setup ()
    {
    uintPtrComparator myComparator;
    mock().installComparator("uintPtr", myComparator);
    }

    void teardown ()
    {
    mock().checkExpectations();
    mock().clear();
    }
};

but get the following errors:

foo.cpp: In member function  virtual void TEST_GROUP_MyTestGroup::setup() :
foo.cpp:67: error: cannot declare variable  myComparator  to be of abstract type  uintPtrComparator
foo.cpp:50: note:   because the following virtual functions are pure within  uintPtrComparator :
include/CppUTestExt/MockNamedValue.h:41: note:       virtual bool MockNamedValueComparator::isEqual(const void*, const void*)
include/CppUTestExt/MockNamedValue.h:42: note:       virtual SimpleString MockNamedValueComparator::valueToString(const void*)

Ryan Hartlage

unread,
Sep 9, 2014, 9:01:36 AM9/9/14
to cppu...@googlegroups.com
Hey William,

Check out custom comparators (MockNamedValueComparator) and withParameterOfType(...).  Custom comparators will let you define the logic for comparing the contents of the pointed-to-structure and withParameterOfType will allow you to specify the comparator to use.

Ryan

William Ivory

unread,
Sep 9, 2014, 9:25:45 AM9/9/14
to cppu...@googlegroups.com
Hi Ryan,

Thanks - as you can see from my last reply I'd started down this road but got stuck with C++ compiler errors.  Turns out that what the error message really meant was that my derived class's implementation of the pure virtual functions in the base class had the wrong parameter types in the prototypes (missing const - whoever maintainst cpputest.org documentation might like to fix that (hint hint)).  Fixed that, and it failed badly due to my having ignored warning 1 in the documentation about the scope of my comparator.  Fixed that and I got a memory leak due to not having called the removeAllComparators() method and bingo - it works.

Thanks again,

William

Mike Finch

unread,
Sep 10, 2014, 9:12:53 AM9/10/14
to cppu...@googlegroups.com
You can always use the Get/Set Data, it's not as elegant as the comparators, but it is TSTTCPW.

    mock().expectOneCall("my_cli_arg_create")
    .withIntParameter("tag", SISF_TAG_BT_CURR_DYN)
    .withPointerParameter("pval", (void *)&test_value)
    .andReturnValue(NULL);

ExecuteFunction()

memcomp(&expectedData, mock().getData("ImportantData"pData), sizeof(expectedData));

static DataStructure data;
    mock_c()->actualCall("my_cli_arg_create")
    ->withIntParameters("tag", tag)
    ->withPointerParameters("pval", (void *)pval)
memcpy(&data, pval, sizeof(data));
mock_c().setPointerData("ImportantData", pData);
    return mock_c()->returnValue().value.pointerValue;

William Ivory

unread,
Sep 10, 2014, 9:16:35 AM9/10/14
to cppu...@googlegroups.com
Gets even less elegant when you have multiple calls to your expected function to check.  Comparators is much cleaner (IMO) and scalable.

Thanks,

William

Vivek Venkatesh

unread,
Apr 2, 2016, 12:08:01 AM4/2/16
to cpputest
Did anyone manage to figure out the clean solution for this problem?

I do not want to verify the pointer parameter, instead I need to do a memcmp of the contents given in expected call and with the one obtained in the actual call.

--Vivek

Ryan Hartlage

unread,
Apr 2, 2016, 8:14:32 AM4/2/16
to cpputest
Vivek,

See above: the feature intended that is intended to solve the problem
is custom comparators. This is how William solved the problem.

Thanks,
Ryan

A. Robert S.

unread,
Apr 6, 2016, 3:22:08 AM4/6/16
to cpputest
Hi William,

This has been fixed recently at cpputest.github.io and should now be correct.

Robert
Reply all
Reply to author
Forward
0 new messages