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@lists.fedorahosted.org > https://lists.fedorahosted.org/mailman/listinfo/sssd-devel _______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel