[SSSD] [PATCH] RFC: Unit test for the NSS responder based on the cmocka library

Sumit Bose sbose at redhat.com
Fri Mar 1 12:54:51 UTC 2013


On Fri, Mar 01, 2013 at 01:39:22PM +0100, Pavel Březina wrote:
> On 02/12/2013 06:12 PM, Jakub Hrozek wrote:
> >Hi,
> >
> >Short version - attached is a patch proposal for a unit test based on
> >cmocka. The patches are an example of a complex, yet isolated unit test
> >and I'd like to get opinions on whether this would be a good way to go.
> >
> >Long version:
> >Our check based test suite is OK for developing simple tests for APIs
> >like sysdb but not really great for testing of more complex interfaces.
> >
> >In particular, it's hard to simulate certain pieces of functionality
> >that require interaction with network or the rest of the system such as
> >LDAP searches or logins, especially in environments like buildsystems.
> >
> >I think we might want to look at Cmocka to provide this missing functionality
> >and test complex interfaces in isolation. Cmocka[1] is a fork of Google's
> >cmockery which is not maintained upstream anymore. Cmocka is maintained
> >by Andreas Schneider.
> >
> >I've been playing with cmocka lately and wrote a couple of patches that
> >add a unit test for the NSS responder, in particular the getpwnam()
> >function. It was quite easy to simulate the Data Provider and the client
> >using two concepts:
> >
> >1) cmocka's mocking feature
> >Functions that provide external interface, like the dummy DP functions
> >in my patches, can access a stack of values. The unit test can push some
> >expected return values onto the stack before launching the test and the
> >dummy functions would then pop the values and use them as appropriate.
> >It's quite easy to simulate a Data Provider saving an entry to cache
> >with call like this (pseudocode):
> >
> >int unit_test()
> >{
> >     will_return(sss_dp_get_account_recv, "testuser");
> >     will_return(sss_dp_get_account_recv, 10);
> >     will_return(sss_dp_get_account_recv, 11);
> >}
> >
> >int sss_dp_get_account_recv(TALLOC_CTX *mem_ctx, tevent_req *req)
> >{
> >     char *username = mock();
> >     uid_t uid = mock();
> >     gid_t gid = mock();
> >
> >     sysdb_store_user(username, uid, gid);
> >}
> >
> >2) the -wrap feature of ld
> >It is possible to selectively override functions from modules linked against
> >to intercept calls using the -wrap feature of ld. In my unit tests I used
> >this feature to check results of responder search with defined callbacks
> >instead of returning the results to the nss client. Here is a simple example
> >of intercepting a call to negative cache to make sure the negative cache
> >is hit when it's supposed to:
> >
> >int __wrap_sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
> >                                  struct sss_domain_info *dom,
> >                                  const char *name)
> >{
> >     int ret;
> >
> >     ret = __real_sss_ncache_check_user(ctx, ttl, dom, name);
> >     if (ret == EEXIST) {
> >         nss_test_ctx->ncache_hit = true;
> >     }
> >     return ret;
> >}
> >
> >There's a couple of boilerplate functions but once these are in place,
> >they can be reused to cover different pieces of functionality..the
> >attached patches test the following requests:
> >  * cached user including assertion that DP was not contacted
> >  * nonexistant user including assertion that on a subsequent lookup, the
> >    request is returned from negative cache
> >  * search for a user that has not been cache prior to the search
> >  * updating an expired user including assertions that the user had been
> >    updated from DP and the updated entry is returned.
> >
> >The downsides of using cmocka as far as I can see are:
> >   * writing the mocking code can be tedious. On the other hand, the NSS
> >     responder I picked was probably the most complex code I could test
> >     as it communicates with both DP and the client library. Even more
> >     isolated testing (the AD sites feature comes to mind) would be much
> >     easier I think.
> >   * cmocka is not present in RHEL
> >
> >I'll be glad to hear comments about this unit test proposal. Patches
> >are attached.
> >
> >[1] http://cmocka.cryptomilk.org/
> 
> Very nice.
> 
> I would like to increase granularity though. First of all we should
> separate cmocka test files from check files on directory/filename
> level. I'd say that all cmocka stuff should go into tests/cmocka. For
> example, there are files common_check.c, common_dom.c, common.c, but
> only common_dom.c is suitable for cmocka. When more common files and
> tests comes, it will be hard to distinguish them.
> 
> Testing with cmocka is mainly about mocking structures and creating
> wrappers around functions. We should try to create reusable mocks and
> wrappers right from the beginning, making them independent on tests.
> For example: mock_rctx(), mock_cctx(), sss_dp_get_account_send(),
> sss_dp_get_account_recv(), ... I believe these and more functions can
> be reused when testing other responders so they should be placed in
> e.g. common_responder.c
> 
> Why did you include setjmp.h?

from cmocka.c:

/*
 * These headers or their equivalents should be included prior to
 * including
 * this header file.
 *
 * #include <stdarg.h>
 * #include <stddef.h>
 * #include <setjmp.h>
 *
 * This allows test applications to use custom definitions of C standard
 * library functions and types.
 */


HTH

bye,
Sumit

>
> _______________________________________________
> sssd-devel mailing list
> sssd-devel at lists.fedorahosted.org
> https://lists.fedorahosted.org/mailman/listinfo/sssd-devel



More information about the sssd-devel mailing list