LCOV - code coverage report
Current view: top level - tests/cmocka - test_krb5_wait_queue.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 132 138 95.7 %
Date: 2015-10-19 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*
       2             :     Copyright (C) 2015 Red Hat
       3             : 
       4             :     SSSD tests: Kerberos wait queue tests
       5             : 
       6             :     This program is free software; you can redistribute it and/or modify
       7             :     it under the terms of the GNU General Public License as published by
       8             :     the Free Software Foundation; either version 3 of the License, or
       9             :     (at your option) any later version.
      10             : 
      11             :     This program is distributed in the hope that it will be useful,
      12             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :     GNU General Public License for more details.
      15             : 
      16             :     You should have received a copy of the GNU General Public License
      17             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include <talloc.h>
      21             : #include <tevent.h>
      22             : #include <errno.h>
      23             : #include <popt.h>
      24             : #include <stdlib.h>
      25             : #include <security/pam_modules.h>
      26             : 
      27             : #include "util/util.h"
      28             : #include "providers/krb5/krb5_common.h"
      29             : #include "providers/krb5/krb5_auth.h"
      30             : #include "tests/cmocka/common_mock.h"
      31             : #include "tests/cmocka/common_mock_be.h"
      32             : 
      33             : struct krb5_mocked_auth_state {
      34             :     const char *user;
      35             :     time_t us_delay;
      36             :     int ret;
      37             :     int pam_status;
      38             :     int dp_err;
      39             : };
      40             : 
      41             : static void krb5_mocked_auth_done(struct tevent_context *ev,
      42             :                                   struct tevent_timer *tt,
      43             :                                   struct timeval tv,
      44             :                                   void *pvt);
      45             : 
      46        1011 : struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
      47             :                                   struct tevent_context *ev,
      48             :                                   struct be_ctx *be_ctx,
      49             :                                   struct pam_data *pd,
      50             :                                   struct krb5_ctx *krb5_ctx)
      51             : {
      52             :     struct tevent_req *req;
      53             :     struct krb5_mocked_auth_state *state;
      54             :     struct tevent_timer *tt;
      55             :     struct timeval tv;
      56             : 
      57        1011 :     req = tevent_req_create(mem_ctx, &state, struct krb5_mocked_auth_state);
      58        1011 :     if (req == NULL) {
      59           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
      60           0 :         return NULL;
      61             :     }
      62             : 
      63        1011 :     state->user = sss_mock_ptr_type(const char *);
      64        1011 :     state->us_delay = sss_mock_type(time_t);
      65        1011 :     state->ret = sss_mock_type(int);
      66        1011 :     state->pam_status = sss_mock_type(int);
      67        1011 :     state->dp_err = sss_mock_type(int);
      68             : 
      69        1011 :     tv = tevent_timeval_current_ofs(0, state->us_delay);
      70             : 
      71        1011 :     tt = tevent_add_timer(ev, req, tv, krb5_mocked_auth_done, req);
      72        1011 :     if (tt == NULL) {
      73           0 :         return NULL;
      74             :     }
      75             : 
      76        1011 :     return req;
      77             : }
      78             : 
      79        1011 : static void krb5_mocked_auth_done(struct tevent_context *ev,
      80             :                                   struct tevent_timer *tt,
      81             :                                   struct timeval tv,
      82             :                                   void *pvt)
      83             : {
      84             :     struct tevent_req *req;
      85             :     struct krb5_mocked_auth_state *state;
      86             : 
      87        1011 :     req = talloc_get_type(pvt, struct tevent_req);
      88        1011 :     state = tevent_req_data(req, struct krb5_mocked_auth_state);
      89             : 
      90        1011 :     DEBUG(SSSDBG_TRACE_LIBS, "Finished auth request of %s\n", state->user);
      91             : 
      92        1011 :     if (state->ret == 0) {
      93        1001 :         tevent_req_done(req);
      94             :     } else {
      95          10 :         tevent_req_error(req, state->ret);
      96             :     }
      97        1011 : }
      98             : 
      99        1011 : int krb5_auth_recv(struct tevent_req *req,
     100             :                    int *_pam_status,
     101             :                    int *_dp_err)
     102             : {
     103             :     struct krb5_mocked_auth_state *state;
     104             : 
     105        1011 :     state = tevent_req_data(req, struct krb5_mocked_auth_state);
     106             : 
     107        1011 :     if (_pam_status != NULL) {
     108        1011 :         *_pam_status = state->pam_status;
     109             :     }
     110             : 
     111        1011 :     if (_dp_err != NULL) {
     112        1011 :         *_dp_err = state->dp_err;
     113             :     }
     114             : 
     115        1021 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     116        1001 :     return EOK;
     117             : }
     118             : 
     119             : struct test_krb5_wait_queue {
     120             :     struct sss_test_ctx *tctx;
     121             :     int num_auths;
     122             :     int num_finished_auths;
     123             : 
     124             :     struct be_ctx *be_ctx;
     125             :     struct pam_data *pd;
     126             :     struct krb5_ctx *krb5_ctx;
     127             : };
     128             : 
     129           3 : static int test_krb5_wait_queue_setup(void **state)
     130             : {
     131             :     struct test_krb5_wait_queue *test_ctx;
     132             : 
     133           3 :     test_ctx = talloc_zero(global_talloc_context,
     134             :                            struct test_krb5_wait_queue);
     135           3 :     assert_non_null(test_ctx);
     136             : 
     137           3 :     test_ctx->tctx = create_ev_test_ctx(test_ctx);
     138           3 :     assert_non_null(test_ctx);
     139             : 
     140           3 :     test_ctx->be_ctx = mock_be_ctx(test_ctx, test_ctx->tctx);
     141           3 :     assert_non_null(test_ctx->be_ctx);
     142             : 
     143           3 :     test_ctx->pd = talloc_zero(test_ctx, struct pam_data);
     144           3 :     assert_non_null(test_ctx->pd);
     145             : 
     146           3 :     test_ctx->krb5_ctx = talloc_zero(test_ctx, struct krb5_ctx);
     147           3 :     assert_non_null(test_ctx->krb5_ctx);
     148             : 
     149           3 :     *state = test_ctx;
     150           3 :     return 0;
     151             : }
     152             : 
     153           3 : static int test_krb5_wait_queue_teardown(void **state)
     154             : {
     155           3 :     struct test_krb5_wait_queue *test_ctx =
     156           3 :         talloc_get_type(*state, struct test_krb5_wait_queue);
     157             : 
     158           3 :     talloc_free(test_ctx);
     159           3 :     return 0;
     160             : }
     161             : 
     162        1011 : static void test_krb5_wait_mock(struct test_krb5_wait_queue *test_ctx,
     163             :                                 const char *username,
     164             :                                 time_t us_delay,
     165             :                                 int ret,
     166             :                                 int pam_status,
     167             :                                 int dp_err)
     168             : {
     169        1011 :     test_ctx->pd->user = discard_const(username);
     170             : 
     171        1011 :     will_return(krb5_auth_send, username);
     172        1011 :     will_return(krb5_auth_send, us_delay);
     173        1011 :     will_return(krb5_auth_send, ret);
     174        1011 :     will_return(krb5_auth_send, pam_status);
     175        1011 :     will_return(krb5_auth_send, dp_err);
     176        1011 : }
     177             : 
     178        1001 : static void test_krb5_wait_mock_success(struct test_krb5_wait_queue *test_ctx,
     179             :                                         const char *username)
     180             : {
     181        1001 :     return test_krb5_wait_mock(test_ctx, username, 200, 0, 0, 0);
     182             : }
     183             : 
     184             : static void test_krb5_wait_queue_single_done(struct tevent_req *req);
     185             : 
     186           1 : static void test_krb5_wait_queue_single(void **state)
     187             : {
     188             :     errno_t ret;
     189             :     struct tevent_req *req;
     190           1 :     struct test_krb5_wait_queue *test_ctx =
     191           1 :         talloc_get_type(*state, struct test_krb5_wait_queue);
     192             : 
     193           1 :     test_krb5_wait_mock_success(test_ctx, "krb5_user");
     194             : 
     195           2 :     req = krb5_auth_queue_send(test_ctx,
     196           1 :                                test_ctx->tctx->ev,
     197             :                                test_ctx->be_ctx,
     198             :                                test_ctx->pd,
     199             :                                test_ctx->krb5_ctx);
     200           1 :     assert_non_null(req);
     201           1 :     tevent_req_set_callback(req, test_krb5_wait_queue_single_done, test_ctx);
     202             : 
     203           1 :     ret = test_ev_loop(test_ctx->tctx);
     204           1 :     assert_int_equal(ret, EOK);
     205           1 : }
     206             : 
     207           1 : static void test_krb5_wait_queue_single_done(struct tevent_req *req)
     208             : {
     209           1 :     struct test_krb5_wait_queue *test_ctx = \
     210           1 :         tevent_req_callback_data(req, struct test_krb5_wait_queue);
     211             :     errno_t ret;
     212             :     int pam_status;
     213             :     int dp_err;
     214             : 
     215           1 :     ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
     216           1 :     talloc_free(req);
     217           1 :     assert_int_equal(ret, EOK);
     218             : 
     219           1 :     test_ev_done(test_ctx->tctx, EOK);
     220           1 : }
     221             : 
     222             : static void test_krb5_wait_queue_multi_done(struct tevent_req *req);
     223             : 
     224           1 : static void test_krb5_wait_queue_multi(void **state)
     225             : {
     226             :     int i;
     227             :     errno_t ret;
     228             :     struct tevent_req *req;
     229           1 :     struct test_krb5_wait_queue *test_ctx =
     230           1 :         talloc_get_type(*state, struct test_krb5_wait_queue);
     231             : 
     232           1 :     test_ctx->num_auths = 1000;
     233             : 
     234        1001 :     for (i=0; i < test_ctx->num_auths; i++) {
     235        1000 :         test_krb5_wait_mock_success(test_ctx, "krb5_user");
     236             : 
     237        2000 :         req = krb5_auth_queue_send(test_ctx,
     238        1000 :                                    test_ctx->tctx->ev,
     239             :                                    test_ctx->be_ctx,
     240             :                                    test_ctx->pd,
     241             :                                    test_ctx->krb5_ctx);
     242        1000 :         assert_non_null(req);
     243        1000 :         tevent_req_set_callback(req, test_krb5_wait_queue_multi_done, test_ctx);
     244             :     }
     245             : 
     246           1 :     ret = test_ev_loop(test_ctx->tctx);
     247           1 :     assert_int_equal(ret, EOK);
     248           1 : }
     249             : 
     250        1000 : static void test_krb5_wait_queue_multi_done(struct tevent_req *req)
     251             : {
     252        1000 :     struct test_krb5_wait_queue *test_ctx = \
     253        1000 :         tevent_req_callback_data(req, struct test_krb5_wait_queue);
     254             :     errno_t ret;
     255             :     int pam_status;
     256             :     int dp_err;
     257             : 
     258        1000 :     ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
     259        1000 :     talloc_free(req);
     260        1000 :     assert_int_equal(ret, EOK);
     261             : 
     262        1000 :     test_ctx->num_finished_auths++;
     263             : 
     264        1000 :     if (test_ctx->num_finished_auths == test_ctx->num_auths) {
     265           1 :         test_ev_done(test_ctx->tctx, EOK);
     266             :     }
     267        1000 : }
     268             : 
     269             : static void test_krb5_wait_queue_fail_odd_done(struct tevent_req *req);
     270             : 
     271           1 : static void test_krb5_wait_queue_fail_odd(void **state)
     272             : {
     273             :     int i;
     274             :     errno_t ret;
     275             :     struct tevent_req *req;
     276           1 :     struct test_krb5_wait_queue *test_ctx =
     277           1 :         talloc_get_type(*state, struct test_krb5_wait_queue);
     278             : 
     279           1 :     test_ctx->num_auths = 10;
     280             : 
     281          11 :     for (i=0; i < test_ctx->num_auths; i++) {
     282          10 :         test_krb5_wait_mock(test_ctx, "krb5_user", 0, i+1 % 2, PAM_SUCCESS, 0);
     283             : 
     284          20 :         req = krb5_auth_queue_send(test_ctx,
     285          10 :                                    test_ctx->tctx->ev,
     286             :                                    test_ctx->be_ctx,
     287             :                                    test_ctx->pd,
     288             :                                    test_ctx->krb5_ctx);
     289          10 :         assert_non_null(req);
     290          10 :         tevent_req_set_callback(req, test_krb5_wait_queue_fail_odd_done, test_ctx);
     291             :     }
     292             : 
     293           1 :     ret = test_ev_loop(test_ctx->tctx);
     294           1 :     assert_int_equal(ret, EOK);
     295           1 : }
     296             : 
     297          10 : static void test_krb5_wait_queue_fail_odd_done(struct tevent_req *req)
     298             : {
     299          10 :     struct test_krb5_wait_queue *test_ctx = \
     300          10 :         tevent_req_callback_data(req, struct test_krb5_wait_queue);
     301             :     errno_t ret;
     302             :     int pam_status;
     303             :     int dp_err;
     304             : 
     305          10 :     ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
     306          10 :     talloc_free(req);
     307          10 :     assert_int_equal(ret, test_ctx->num_finished_auths+1 % 2);
     308             : 
     309          10 :     test_ctx->num_finished_auths++;
     310             : 
     311          10 :     if (test_ctx->num_finished_auths == test_ctx->num_auths) {
     312           1 :         test_ev_done(test_ctx->tctx, EOK);
     313             :     }
     314          10 : }
     315             : 
     316           1 : int main(int argc, const char *argv[])
     317             : {
     318             :     poptContext pc;
     319             :     int opt;
     320           6 :     struct poptOption long_options[] = {
     321             :         POPT_AUTOHELP
     322           5 :         SSSD_DEBUG_OPTS
     323             :         POPT_TABLEEND
     324             :     };
     325             : 
     326           1 :     const struct CMUnitTest tests[] = {
     327             :         /* Run a single auth request */
     328             :         cmocka_unit_test_setup_teardown(test_krb5_wait_queue_single,
     329             :                                         test_krb5_wait_queue_setup,
     330             :                                         test_krb5_wait_queue_teardown),
     331             : 
     332             :         /* Run multiple auth requests */
     333             :         cmocka_unit_test_setup_teardown(test_krb5_wait_queue_multi,
     334             :                                         test_krb5_wait_queue_setup,
     335             :                                         test_krb5_wait_queue_teardown),
     336             : 
     337             :         /* Make sure that all requests in queue run even if some fail */
     338             :         cmocka_unit_test_setup_teardown(test_krb5_wait_queue_fail_odd,
     339             :                                         test_krb5_wait_queue_setup,
     340             :                                         test_krb5_wait_queue_teardown),
     341             :     };
     342             : 
     343             :     /* Set debug level to invalid value so we can deside if -d 0 was used. */
     344           1 :     debug_level = SSSDBG_INVALID;
     345             : 
     346           1 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
     347           1 :     while((opt = poptGetNextOpt(pc)) != -1) {
     348             :         switch(opt) {
     349             :         default:
     350           0 :             fprintf(stderr, "\nInvalid option %s: %s\n\n",
     351             :                     poptBadOption(pc, 0), poptStrerror(opt));
     352           0 :             poptPrintUsage(pc, stderr, 0);
     353           0 :             return 1;
     354             :         }
     355             :     }
     356           1 :     poptFreeContext(pc);
     357             : 
     358           1 :     DEBUG_CLI_INIT(debug_level);
     359             : 
     360             :     /* Even though normally the tests should clean up after themselves
     361             :      * they might not after a failed run. Remove the old db to be sure */
     362           1 :     tests_set_cwd();
     363             : 
     364           1 :     return cmocka_run_group_tests(tests, NULL, NULL);
     365             : }

Generated by: LCOV version 1.10