nsswitch: add test for parallel NSS & libwbclient calls
authorRalph Wuerthner <ralph.wuerthner@de.ibm.com>
Fri, 5 Oct 2018 11:53:30 +0000 (13:53 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 1 Nov 2018 00:59:10 +0000 (01:59 +0100)
Signed-off-by: Ralph Wuerthner <ralph.wuerthner@de.ibm.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
nsswitch/stress-nss-libwbclient.c [new file with mode: 0644]
nsswitch/wscript_build

diff --git a/nsswitch/stress-nss-libwbclient.c b/nsswitch/stress-nss-libwbclient.c
new file mode 100644 (file)
index 0000000..cf85ff3
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Stress test for parallel NSS & libwbclient calls.
+
+   Copyright (C) Ralph Wuerthner 2018
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <wbclient.h>
+
+#define RUNTIME 10
+
+struct thread_state {
+       const char *username;
+       time_t timeout;
+       pthread_mutex_t lock;
+       bool fail;
+       int nss_loop_count;
+       int wbc_loop_count;
+};
+
+static void *query_nss_thread(void *ptr)
+{
+       struct thread_state *state = ptr;
+       char buf[1024];
+       int rc;
+       struct passwd pwd, *result;
+
+       while (time(NULL) < state->timeout) {
+               rc = getpwnam_r(state->username,
+                               &pwd,
+                               buf,
+                               sizeof(buf),
+                               &result);
+               if (rc != 0 || result == NULL) {
+                       pthread_mutex_lock(&state->lock);
+                       state->fail = true;
+                       pthread_mutex_unlock(&state->lock);
+                       fprintf(stderr,
+                               "getpwnam_r failed with rc='%s' result=%p\n",
+                               strerror(rc),
+                               result);
+                       break;
+               }
+               state->nss_loop_count++;
+               pthread_mutex_lock(&state->lock);
+               if (state->fail) {
+                       pthread_mutex_unlock(&state->lock);
+                       break;
+               }
+               pthread_mutex_unlock(&state->lock);
+       }
+       return NULL;
+}
+
+static void *query_wbc_thread(void *ptr)
+{
+       struct thread_state *state = ptr;
+       struct passwd *ppwd;
+       wbcErr wbc_status;
+
+       while (time(NULL) < state->timeout) {
+               wbc_status = wbcGetpwnam(state->username, &ppwd);
+               if (!WBC_ERROR_IS_OK(wbc_status)) {
+                       pthread_mutex_lock(&state->lock);
+                       state->fail = true;
+                       pthread_mutex_unlock(&state->lock);
+                       fprintf(stderr,
+                               "wbcGetpwnam failed with %s\n",
+                               wbcErrorString(wbc_status));
+                       break;
+               }
+               wbcFreeMemory(ppwd);
+               state->wbc_loop_count++;
+               pthread_mutex_lock(&state->lock);
+               if (state->fail) {
+                       pthread_mutex_unlock(&state->lock);
+                       break;
+               }
+               pthread_mutex_unlock(&state->lock);
+       }
+       return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+       int rc, n;
+       struct thread_state state;
+       pthread_t threads[2];
+
+       if (argc < 2 ) {
+               fprintf(stderr,"%s: missing domain user\n", argv[0]);
+               return 1;
+       }
+
+       state.username = argv[1];
+       state.timeout = time(NULL) + RUNTIME;
+       pthread_mutex_init(&state.lock, NULL);
+       state.fail = false;
+       state.nss_loop_count = 0;
+       state.wbc_loop_count = 0;
+
+       printf("query domain user '%s'\n", state.username);
+
+       /* create query threads */
+       rc = pthread_create(&threads[0], NULL, query_nss_thread, &state);
+       if (rc != 0) {
+               fprintf(stderr,
+                       "creating NSS thread failed: %s\n",
+                       strerror(rc));
+               exit(1);
+       }
+       rc = pthread_create(&threads[1], NULL, query_wbc_thread, &state);
+       if (rc != 0) {
+               fprintf(stderr,
+                       "creating libwbclient thread failed: %s\n",
+                       strerror(rc));
+               exit(1);
+       }
+
+       /* wait for query threads to terminate */
+       for (n = 0; n < 2; n++) {
+               pthread_join(threads[n], NULL);
+       }
+
+       fprintf(state.fail ? stderr: stdout,
+               "test %s with %i NSS and %i libwbclient calls\n",
+               state.fail ? "failed" : "passed",
+               state.nss_loop_count,
+               state.wbc_loop_count);
+
+       return state.fail;
+}
index ff98372fd6e26948d8d0170c8009661d2bf354a0..6acc4a19b9b4a2383427614bd09543629095a796 100644 (file)
@@ -17,6 +17,13 @@ bld.SAMBA_BINARY('nsstest',
                  install=False
                 )
 
+if bld.CONFIG_SET('HAVE_PTHREAD'):
+    bld.SAMBA_BINARY('stress-nss-libwbclient',
+                    source='stress-nss-libwbclient.c',
+                    deps='wbclient',
+                    install=False
+                    )
+
 # The nss_wrapper code relies strictly on the linux implementation and
 # name, so compile but do not install a copy under this name.
 bld.SAMBA_LIBRARY('nss_wrapper_winbind',