Alex Rivera | Logout

Advice on Mocking System Calls

Asked 2010-05-27T19:58:55.510
32

I have a class which calls getaddrinfo for DNS look ups. During testing I want to simulate various error conditions involving this system call. What's the recommended method for mocking system calls like this? I'm using Boost.Test for my unit testing.

Edit
Report

1 Answer

15

You have three options:

  1. Use the GNU linker's mocking abilities, the --wrap option. I've never used this to test production code as I didn't find out about it until our dev team had committed to method 3. I wish we had found this sooner.

     ld --wrap=getaddrinfo /*the rest of the link line*/
     or
     g++ -Wl,--wrap=getaddrinfo /* the rest of the build line*/
    
     // this in the unit tests.
     bool g_getaddrinfo_use_real = true;
     int g_getaddrinfo_ret = -1;
     int g_getaddrinfo_errno = something;
     int __wrap_getaddrinfo( const char *node, const char *service,
                             const struct addrinfo *hints,
                             struct addrinfo **res )
     {
        if( g_getaddrinfo_use_real )
           return __real_getaddrinfo(node,service,hints,res);
    
        errno = g_getaddrinfo_errno;
        return g_getaddrinfo_ret;
     }
    
  2. Define your own getaddrinfo() and link it statically to your test application. This will only work if libc is linked dynamically (which is true 99% of the time). This method also has the disadvantage of permanently disabling the real getaddrinfo() in your unit test application, but is incredibly simple to implement.

     int g_getadderinfo_ret = -1;
     int g_getaddrinfo_errno = something;
     int getaddrinfo( const char *node, const char *service,
                      const struct addrinfo *hints,
                      struct addrinfo **res )
     {
        errno = g_getaddrinfo_errno
        return g_getaddrinfo_ret;
     }
    
  3. Define your own intermediary function with the same name. Then you can still call the original if you want. This is much easier with some macros to help with the repetition. Also you will have to use GNU extensions if you wan to mock variadic functions (printf, open, etc).

     typedef int (*getaddrinfo_func_type)( const char *node,
                                           const char *service,
      
answered 2010-05-28T00:08:22.923

Your Answer