Mocking system calls in google mock

7,623 views
Skip to first unread message

kalkotivinay

unread,
Apr 13, 2009, 1:02:42 AM4/13/09
to Google C++ Mocking Framework
Hi,

I am using google mock to unit my code. I have used some system calls
in my code like open(), read() and write() and I do want to mock these
system calls.

Please let me know how can I do this ?

Thanks,
Vinay

Zhanyong Wan (λx.x x)

unread,
Apr 13, 2009, 1:07:04 AM4/13/09
to kalkotivinay, Google C++ Mocking Framework

Keith Ray

unread,
Apr 13, 2009, 3:17:46 PM4/13/09
to kalkotivinay, Google C++ Mocking Framework
I suggest introducing an adapter for those system calls (create a
class that handles open/read/write/close) and mock the interface of
that adapter when testing code that uses that adapter.

This is related to the idea of "don't mock code you don't own".

On Sun, Apr 12, 2009 at 10:02 PM, kalkotivinay <kalkot...@gmail.com> wrote:

--
C. Keith Ray, IXP Coach, Industrial Logic, Inc.
http://industriallogic.com 866-540-8336 (toll free)
Groove with our Agile Greatest Hits: http://www.industriallogic.com/elearning/
http://agilesolutionspace.blogspot.com/

kalkotivinay

unread,
May 13, 2009, 1:39:10 AM5/13/09
to Google C++ Mocking Framework

Hi,

This is how I am trying to mock the system calls.

I have an interface class -

// syscallinterface.hpp
class syscallinterface
{
public:
virtual int Open(const char *path, int flags) = 0;
};

//syscall.hpp
#include "syscallinterface.hpp
class syscall: public syscallinterface
{
public:
int Open(const char *path, int flags) {
return open(path, flags);
}

//mocksyscall.hpp
#include syscallinterface.hpp
class syscall: public syscallinterface
{
public:
int Open(const char *path, int flags);
};

class MockSysCall : public syscall
{

public:
MOCK_METHOD2( Open, int(const char *pathname, int flags ));
};

In my foo class, I am trying to test createfoo method which is using
syscall::Open().

// FooTest.cpp

mocksyscall mocksystemcall;
EXPECT_CALL( mocksystemcall, System(_)).WillRepeatedly(Return(-1));
int status = foo::createfoo();

I am expecting createfoo() to return -1 for syscall::Open() and it is
not.
Looks like its not even calling the mock method.

Can anyone help me on this.

Thanks,
Vinay

On Apr 14, 12:17 am, Keith Ray <keith....@gmail.com> wrote:
> I suggest introducing an adapter for those system calls (create a
> class that handles open/read/write/close) and mock the interface of
> that adapter when testing code that uses that adapter.
>
> This is related to the idea of "don't mock code you don't own".
>
> On Sun, Apr 12, 2009 at 10:02 PM, kalkotivinay <kalkoti.vi...@gmail.com> wrote:
> > I am using google mock to unit my code. I have used some system calls
> > in my code like open(), read() and write() and I do want to mock these
> > system calls.
>
> > Please let me know how can I do this ?
>
> --
> C. Keith Ray, IXP Coach, Industrial Logic, Inc.http://industriallogic.com     866-540-8336 (toll free)

Zhanyong Wan (λx.x x)

unread,
May 13, 2009, 1:49:04 AM5/13/09
to kalkotivinay, Google C++ Mocking Framework
On Tue, May 12, 2009 at 10:39 PM, kalkotivinay <kalkot...@gmail.com> wrote:
>
>
> Hi,
>
> This is how I am trying to mock the system calls.
>
> I have an interface class -
>
> // syscallinterface.hpp
> class syscallinterface
> {
> public:
> virtual int Open(const char *path, int flags) = 0;
> };
>
> //syscall.hpp
> #include "syscallinterface.hpp
> class syscall: public syscallinterface
> {
> public:
> int Open(const char *path, int flags) {
> return open(path, flags);
> }
>
> //mocksyscall.hpp
> #include syscallinterface.hpp
> class syscall: public syscallinterface
> {
> public:
> int Open(const char *path, int flags);
> };

You are defining class syscall in both syscall.hpp and
mocksyscall.hpp. If you use both headers in the same program, you
violate the one-definition rule and your code is invalid.

> class MockSysCall : public syscall
> {
>
> public:
> MOCK_METHOD2( Open, int(const char *pathname, int flags ));
> };

I would remove class syscall from mocksyscall.hpp and write this
instead:

class MockSysCall : public syscallinterface { ... };

> In my foo class, I am trying to test createfoo method which is using
> syscall::Open().
>
> // FooTest.cpp
>
> mocksyscall mocksystemcall;
> EXPECT_CALL( mocksystemcall, System(_)).WillRepeatedly(Return(-1));

Is System(_) a typo? I thought you want Open().

> int status = foo::createfoo();
>
> I am expecting createfoo() to return -1 for syscall::Open() and it is
> not.
> Looks like its not even calling the mock method.

Try running your program with the --gmock_verbose=info command-line
flag. It tells you which mock methods are called.

> Can anyone help me on this.
>
> Thanks,
> Vinay
>
> On Apr 14, 12:17 am, Keith Ray <keith....@gmail.com> wrote:
>> I suggest introducing an adapter for those system calls (create a
>> class that handles open/read/write/close) and mock the interface of
>> that adapter when testing code that uses that adapter.
>>
>> This is related to the idea of "don't mock code you don't own".
>>
>> On Sun, Apr 12, 2009 at 10:02 PM, kalkotivinay <kalkoti.vi...@gmail.com> wrote:
>> > I am using google mock to unit my code. I have used some system calls
>> > in my code like open(), read() and write() and I do want to mock these
>> > system calls.
>>
>> > Please let me know how can I do this ?
>>
>> --
>> C. Keith Ray, IXP Coach, Industrial Logic, Inc.http://industriallogic.com 866-540-8336 (toll free)
>> Groove with our Agile Greatest Hits:http://www.industriallogic.com/elearning/http://agilesolutionspace.blogspot.com/
>

--
Zhanyong

kalkotivinay

unread,
May 13, 2009, 2:07:53 AM5/13/09
to Google C++ Mocking Framework
I tried deriving mocksyscall from syscallinterface

class mocksyscall : public syscallinterface { ... };

I am getting the following error -
FooTest.cpp: error: cannot declare variable 'mocksystemcall' to be of
abstract type 'mocksyscall'.



On May 13, 10:49 am, Zhanyong Wan (λx.x x) <w...@google.com> wrote:
> >> Groove with our Agile Greatest Hits:http://www.industriallogic.com/elearning/http://agilesolutionspace.bl...
>
> --
> Zhanyong

Zhanyong Wan (λx.x x)

unread,
May 13, 2009, 2:12:49 AM5/13/09
to kalkotivinay, Google C++ Mocking Framework
On Tue, May 12, 2009 at 11:07 PM, kalkotivinay <kalkot...@gmail.com> wrote:
>
> I tried deriving mocksyscall from syscallinterface
>
> class mocksyscall : public syscallinterface { ... };
>
> I am getting the following error -
> FooTest.cpp: error: cannot declare variable 'mocksystemcall' to be of
> abstract type 'mocksyscall'.

It appears that your mocksyscall class missed some pure virtual
methods in syscallinterface. Please show us your real code.

--
Zhanyong

kalkotivinay

unread,
May 13, 2009, 2:25:23 AM5/13/09
to Google C++ Mocking Framework
// SysCallInterface.hpp
class SysCallInterface
{
public:
virtual int Open(const char *pathname, int flags) = 0;
};


// MockSysCall.hpp

#include "../hdr/SysCallInterface.hpp"

class MockSysCall : public SysCallInterface
{

public:
MOCK_METHOD2( Open, int(const char *pathname, int flags ));
};

// FooTest.cpp
#include "MockSysCall.hpp

class FooTest : public testing::Test
{
// some attributes.
virtual void SetUp() { ... }
};

TEST_F( FooTest, createfoo )
{
MockSysCall mocksystemcall;
SysCallInterface *sc;
sc = &mocksystemcall;

EXPECT_CALL( *sc, Open(_)).WillRepeatedly(Return(-1));

}

Thanks,
Vinay

On May 13, 11:12 am, Zhanyong Wan (λx.x x) <w...@google.com> wrote:

Zhanyong Wan (λx.x x)

unread,
May 13, 2009, 2:31:19 AM5/13/09
to kalkotivinay, Google C++ Mocking Framework
On Tue, May 12, 2009 at 11:25 PM, kalkotivinay <kalkot...@gmail.com> wrote:
>
> // SysCallInterface.hpp
> class SysCallInterface
> {
> public:

BTW, you should have

virtual ~SysCallInterface() {}

here as the class is meant to be inherited from.

>  virtual int Open(const char *pathname, int flags) = 0;
> };
>
>
> // MockSysCall.hpp
>
> #include "../hdr/SysCallInterface.hpp"
>
> class MockSysCall : public SysCallInterface
> {
>
> public:
>  MOCK_METHOD2( Open, int(const char *pathname, int flags ));
> };
>
> // FooTest.cpp
> #include "MockSysCall.hpp
>
> class FooTest : public testing::Test
> {
>  // some attributes.
>  virtual void SetUp() { ... }
> };
>
> TEST_F( FooTest, createfoo )
> {
>  MockSysCall mocksystemcall;
>  SysCallInterface *sc;
>  sc = &mocksystemcall;
>
>  EXPECT_CALL( *sc, Open(_)).WillRepeatedly(Return(-1));

Use mocksystemcall instead of *sc in this statement. The first
argument to EXPECT_CALL must be a mock object.

--
Zhanyong

kalkotivinay

unread,
May 13, 2009, 2:39:17 AM5/13/09
to Google C++ Mocking Framework

I am getting the error for line where i have declared 'MockSysCall
mocksystemcall;'
FooTest.cpp: error: cannot declare variable 'mocksystemcall' to be of
abstract type 'mocksyscall'

Does gmock define any function for Open when I use MOCK_METHODD() ?.

Thanks,
Vinay

On May 13, 11:31 am, Zhanyong Wan (λx.x x) <w...@google.com> wrote:

kalkotivinay

unread,
May 13, 2009, 2:52:28 AM5/13/09
to Google C++ Mocking Framework

One more thing, the foo class implementation is in a dynamic library
and i have included the library in fooTest's Makefile.

Just wondering how gtest would mock the methods ?.

Zhanyong Wan (λx.x x)

unread,
May 13, 2009, 2:58:48 AM5/13/09
to kalkotivinay, Google C++ Mocking Framework
On Tue, May 12, 2009 at 11:39 PM, kalkotivinay <kalkot...@gmail.com> wrote:
>
>
> I am getting the error for line where i have declared 'MockSysCall
> mocksystemcall;'
> FooTest.cpp: error: cannot declare variable 'mocksystemcall' to be of
> abstract type 'mocksyscall'

What is 'mocksyscall'? I only see MockSysCall in your code. Is this
the real error message? Please post the real message. Please also
post the version and name of your compiler.

> Does gmock define any function for Open when I use MOCK_METHODD() ?.

Yes, it implements Open.

--
Zhanyong

Zhanyong Wan (λx.x x)

unread,
May 13, 2009, 3:13:07 AM5/13/09
to kalkotivinay, Google C++ Mocking Framework
On Tue, May 12, 2009 at 11:39 PM, kalkotivinay <kalkot...@gmail.com> wrote:
>
>
> I am getting the error for line where i have declared 'MockSysCall
> mocksystemcall;'
> FooTest.cpp: error: cannot declare variable 'mocksystemcall' to be of
> abstract type 'mocksyscall'

I have to change Open(_) to Open(_, _). Then I can compile it using gcc 4.

Do you have a macro "#define Open(x, y) ...." somewhere? Can you try
to rename Open() to something different?

--
Zhanyong

kalkotivinay

unread,
May 13, 2009, 3:17:44 AM5/13/09
to Google C++ Mocking Framework
Sorry for the confusion.

This is the real message.
FooTest.cpp:85: error: cannot declare variable 'mocksystemcall' to be
of abstract type 'MockSysCall'

I am using gcc 4.3.2

Thanks,
Vinay

On May 13, 11:58 am, Zhanyong Wan (λx.x x) <w...@google.com> wrote:

kalkotivinay

unread,
May 13, 2009, 3:27:57 AM5/13/09
to Google C++ Mocking Framework

Hi,

They are some typos. copy-paste is not working on my machine for some
reason.
I am using Open(_,_) and there are no #defines for Open.

Thanks,
Vinay

Zhanyong Wan (λx.x x)

unread,
May 13, 2009, 3:35:24 AM5/13/09
to kalkotivinay
(bcc googlemock to avoid bothering others)

On Wed, May 13, 2009 at 12:27 AM, kalkotivinay <kalkot...@gmail.com> wrote:
>
>
> Hi,
>
> They are some typos. copy-paste is not working on my machine for some
> reason.

It's important we are looking at the actual code. Could you reduce
your code to the bare minimum that shows the problem (ideally in one
file) and attach your file?

> I am using Open(_,_) and there are no #defines for Open.

Have you tried to rename Open() to something else as suggested? If
that fixed the problem, you might have a #define Open(...) in some
header you #include.

--
Zhanyong

kalkotivinay

unread,
May 13, 2009, 5:38:49 AM5/13/09
to Google C++ Mocking Framework
Hi Zhanyong,

I fixed it. It was because of the parameter miss match. In the base
class I was using const char * for path attribute and for mocked
object, I was just using char *.

But, its still not working fine properly. Foo::CreateFooService() is
not returning 4.

Here is my entire code.

// SysCallInterface file
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

class SysCallInterface
{
public:
virtual int os_open(const char *pathname, int flags) = 0;
virtual int os_open(const char *pathname, int flags, mode_t mode) =
0;
virtual ssize_t os_read(int fd, void *buf, size_t count) = 0;
virtual ssize_t os_write(int fd, void *buf, size_t count) = 0;
virtual int os_stat(const char *path, struct stat *buf) = 0;
virtual int os_system(const char *command) = 0;
virtual int os_close(int fd) = 0;
virtual int os_remove(const char *pathname) = 0;
};


// SysCall.hpp
class SysCall: public SysCallInterface
{
public:
int os_open(const char *pathname, int flags) {
return open(pathname, flags);
}

int os_open(const char *pathname, int flags, mode_t mode) {
return open(pathname, flags, mode);
}

ssize_t os_read(int fd, void *buf, size_t count) {
return read(fd, buf, count);
}

ssize_t os_write(int fd, void *buf, size_t count) {
return write(fd, buf, count);
}

int os_stat(const char *path, struct stat *buf) {
return stat(path, buf);
}

int os_system(const char *command) {
return system(command);
}

int os_close(int fd) {
return close(fd);
}

int os_remove(const char *pathname) {
return remove(pathname);
}
};


// MockSysCall.hpp


class MockSysCall : public SysCallInterface
{
public:
MOCK_METHOD2( os_open, int(const char *pathname, int flags ));
MOCK_METHOD3( os_open, int(const char *pathname, int flags, mode_t
mode ));
MOCK_METHOD3( os_read, ssize_t(int fd, void *buf, size_t count ));
MOCK_METHOD3( os_write, ssize_t(int fd, void *buf, size_t count ));
MOCK_METHOD2( os_stat, int(const char *path, struct stat *buf ));
MOCK_METHOD1( os_system, int(const char *command ));
MOCK_METHOD1( os_close, int(int fd ));
MOCK_METHOD1( os_remove, int(const char *pathname ));
};



// FooTest.cpp
#include <MockSysCall.hpp>

using testing::Return;
using testing::_;

class FooServiceTest : public testing::Test
{
protected:
virtual void SetUp(){ ...}
};

TEST_F( FooServiceTest, CreateFooService )
{
MockSysCall mocksystemcall;
EXPECT_CALL( mocksystemcall, os_system(_))
.WillRepeatedly(Return(-1));
int status = FooService::CreateFooService(); // this is not
returning 4.
EXPECT_EQ( 4, status );
}

// Foo.cpp

int FooService::CreateFooService
{
SysCallInterface *sci;
SysCall sc;
sci = &sc;
...
if( sci->os_system(cmd) == -1 )
{
return 4;
}
return 0;
}


On May 13, 12:35 pm, Zhanyong Wan (λx.x x) <w...@google.com> wrote:
> (bcc googlemock to avoid bothering others)
>

Bruce Trask

unread,
May 13, 2009, 11:21:18 AM5/13/09
to Google C++ Mocking Framework, kalkotivinay

> int FooService::CreateFooService
> {
> SysCallInterface *sci;
> SysCall sc;
> sci = &sc;
> ...
> if( sci->os_system(cmd) == -1 )
> {
> return 4;
> }
> return 0;
> }

Your function under test is not using a mock object but rather instantiating a real one (i.e. SysCall). You will need to break the dependency in this function so that you can pass in or otherwise use an instance of MockSysCall instead.

Regards,
Bruce

--- On Wed, 5/13/09, kalkotivinay <kalkot...@gmail.com> wrote:

kalkotivinay

unread,
May 14, 2009, 12:19:21 AM5/14/09
to Google C++ Mocking Framework
FooService::CreateFooService () is my code under test. I cannot
replace SysCallInterface pointer with MockSysCall object.

Is there anyother way of dealing with this. One way is to pass
SysCallInterface object as the argument. But I don't want to do that.


On May 13, 8:21 pm, Bruce Trask <bruce.tr...@mdesystems.com> wrote:
> > int FooService::CreateFooService
> > {
> >   SysCallInterface *sci;
> >   SysCall sc;
> >   sci = &sc;
> >   ...
> >   if( sci->os_system(cmd) == -1 )
> >   {
> >     return 4;
> >   }
> >   return 0;
> > }
>
> Your function under test is not using a mock object but rather instantiating a real one (i.e. SysCall).  You will need to break the dependency in this function so that you can pass in or otherwise use an instance of MockSysCall instead.
>
> Regards,
> Bruce
>
> --- On Wed, 5/13/09, kalkotivinay <kalkoti.vi...@gmail.com> wrote:

Bruce Trask

unread,
May 14, 2009, 11:02:40 AM5/14/09
to Google C++ Mocking Framework, kalkotivinay

Many times you have to change the code under test to get it fully "under test". It is worth it to do so as you can then more fully benefit from the facilities that frameworks like gmock provide.

Regards,
Bruce

--- On Thu, 5/14/09, kalkotivinay <kalkot...@gmail.com> wrote:

Reply all
Reply to author
Forward
0 new messages