LCOV - code coverage report
Current view: top level - nsswitch - stress-nss-libwbclient.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 41 65 63.1 %
Date: 2021-09-23 10:06:22 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Stress test for parallel NSS & libwbclient calls.
       5             : 
       6             :    Copyright (C) Ralph Wuerthner 2018
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include <stdio.h>
      23             : #include <stdint.h>
      24             : #include <stdbool.h>
      25             : #include <pthread.h>
      26             : #include <string.h>
      27             : #include <unistd.h>
      28             : #include <time.h>
      29             : #include <stdlib.h>
      30             : #include <sys/types.h>
      31             : #include <pwd.h>
      32             : #include <wbclient.h>
      33             : 
      34             : #define RUNTIME 10
      35             : 
      36             : struct thread_state {
      37             :         const char *username;
      38             :         time_t timeout;
      39             :         pthread_mutex_t lock;
      40             :         bool fail;
      41             :         int nss_loop_count;
      42             :         int wbc_loop_count;
      43             : };
      44             : 
      45           2 : static void *query_nss_thread(void *ptr)
      46             : {
      47           2 :         struct thread_state *state = ptr;
      48             :         char buf[1024];
      49             :         int rc;
      50             :         struct passwd pwd, *result;
      51             : 
      52         538 :         while (time(NULL) < state->timeout) {
      53         534 :                 rc = getpwnam_r(state->username,
      54             :                                 &pwd,
      55             :                                 buf,
      56             :                                 sizeof(buf),
      57             :                                 &result);
      58         534 :                 if (rc != 0 || result == NULL) {
      59           0 :                         pthread_mutex_lock(&state->lock);
      60           0 :                         state->fail = true;
      61           0 :                         pthread_mutex_unlock(&state->lock);
      62           0 :                         fprintf(stderr,
      63             :                                 "getpwnam_r failed with rc='%s' result=%p\n",
      64             :                                 strerror(rc),
      65             :                                 result);
      66           0 :                         break;
      67             :                 }
      68         534 :                 state->nss_loop_count++;
      69         534 :                 pthread_mutex_lock(&state->lock);
      70         534 :                 if (state->fail) {
      71           0 :                         pthread_mutex_unlock(&state->lock);
      72           0 :                         break;
      73             :                 }
      74         534 :                 pthread_mutex_unlock(&state->lock);
      75             :         }
      76           2 :         return NULL;
      77             : }
      78             : 
      79           2 : static void *query_wbc_thread(void *ptr)
      80             : {
      81           2 :         struct thread_state *state = ptr;
      82             :         struct passwd *ppwd;
      83             :         wbcErr wbc_status;
      84             : 
      85       31564 :         while (time(NULL) < state->timeout) {
      86       31560 :                 wbc_status = wbcGetpwnam(state->username, &ppwd);
      87       31560 :                 if (!WBC_ERROR_IS_OK(wbc_status)) {
      88           0 :                         pthread_mutex_lock(&state->lock);
      89           0 :                         state->fail = true;
      90           0 :                         pthread_mutex_unlock(&state->lock);
      91           0 :                         fprintf(stderr,
      92             :                                 "wbcGetpwnam failed with %s\n",
      93             :                                 wbcErrorString(wbc_status));
      94           0 :                         break;
      95             :                 }
      96       31560 :                 wbcFreeMemory(ppwd);
      97       31560 :                 state->wbc_loop_count++;
      98       31560 :                 pthread_mutex_lock(&state->lock);
      99       31560 :                 if (state->fail) {
     100           0 :                         pthread_mutex_unlock(&state->lock);
     101           0 :                         break;
     102             :                 }
     103       31560 :                 pthread_mutex_unlock(&state->lock);
     104             :         }
     105           2 :         return NULL;
     106             : }
     107             : 
     108           2 : int main(int argc, char *argv[])
     109             : {
     110             :         int rc, n;
     111             :         struct thread_state state;
     112             :         pthread_t threads[2];
     113             : 
     114           2 :         if (argc < 2 ) {
     115           0 :                 fprintf(stderr,"%s: missing domain user\n", argv[0]);
     116           0 :                 return 1;
     117             :         }
     118             : 
     119           2 :         state.username = argv[1];
     120           2 :         state.timeout = time(NULL) + RUNTIME;
     121           2 :         rc = pthread_mutex_init(&state.lock, NULL);
     122           2 :         if (rc != 0) {
     123           0 :                 fprintf(stderr,
     124             :                         "pthread_mutex_init failed: %s\n",
     125             :                         strerror(rc));
     126           0 :                 exit(1);
     127             :         }
     128           2 :         state.fail = false;
     129           2 :         state.nss_loop_count = 0;
     130           2 :         state.wbc_loop_count = 0;
     131             : 
     132           2 :         printf("query domain user '%s'\n", state.username);
     133             : 
     134             :         /* create query threads */
     135           2 :         rc = pthread_create(&threads[0], NULL, query_nss_thread, &state);
     136           2 :         if (rc != 0) {
     137           0 :                 fprintf(stderr,
     138             :                         "creating NSS thread failed: %s\n",
     139             :                         strerror(rc));
     140           0 :                 exit(1);
     141             :         }
     142           2 :         rc = pthread_create(&threads[1], NULL, query_wbc_thread, &state);
     143           2 :         if (rc != 0) {
     144           0 :                 fprintf(stderr,
     145             :                         "creating libwbclient thread failed: %s\n",
     146             :                         strerror(rc));
     147           0 :                 exit(1);
     148             :         }
     149             : 
     150             :         /* wait for query threads to terminate */
     151           6 :         for (n = 0; n < 2; n++) {
     152           4 :                 rc = pthread_join(threads[n], NULL);
     153           4 :                 if (rc != 0) {
     154           0 :                         fprintf(stderr,
     155             :                                 "joining query thread %i failed: %s\n",
     156             :                                 n,
     157             :                                 strerror(rc));
     158           0 :                         exit(1);
     159             :                 }
     160             :         }
     161             : 
     162           4 :         fprintf(state.fail ? stderr: stdout,
     163             :                 "test %s with %i NSS and %i libwbclient calls\n",
     164           2 :                 state.fail ? "failed" : "passed",
     165             :                 state.nss_loop_count,
     166             :                 state.wbc_loop_count);
     167             : 
     168           2 :         return state.fail;
     169             : }

Generated by: LCOV version 1.13