1/* 2 Unix SMB/CIFS implementation. 3 4 testing of the events subsystem 5 6 Copyright (C) Stefan Metzmacher 2006-2009 7 8 ** NOTE! The following LGPL license applies to the tevent 9 ** library. This does NOT imply that all of Samba is released 10 ** under the LGPL 11 12 This library is free software; you can redistribute it and/or 13 modify it under the terms of the GNU Lesser General Public 14 License as published by the Free Software Foundation; either 15 version 3 of the License, or (at your option) any later version. 16 17 This library is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Lesser General Public License for more details. 21 22 You should have received a copy of the GNU Lesser General Public 23 License along with this library; if not, see <http://www.gnu.org/licenses/>. 24*/ 25 26#include "includes.h" 27#include "lib/events/events.h" 28#include "system/filesys.h" 29#include "torture/torture.h" 30 31static int fde_count; 32 33static void fde_handler(struct tevent_context *ev_ctx, struct tevent_fd *f, 34 uint16_t flags, void *private_data) 35{ 36 int *fd = (int *)private_data; 37 char c; 38#ifdef SA_SIGINFO 39 kill(getpid(), SIGUSR1); 40#endif 41 kill(getpid(), SIGALRM); 42 read(fd[0], &c, 1); 43 write(fd[1], &c, 1); 44 fde_count++; 45} 46 47static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te, 48 struct timeval tval, void *private_data) 49{ 50 int *finished = (int *)private_data; 51 (*finished) = 1; 52} 53 54static void count_handler(struct tevent_context *ev_ctx, struct signal_event *te, 55 int signum, int count, void *info, void *private_data) 56{ 57 int *countp = (int *)private_data; 58 (*countp) += count; 59} 60 61static bool test_event_context(struct torture_context *test, 62 const void *test_data) 63{ 64 struct tevent_context *ev_ctx; 65 int fd[2] = { -1, -1 }; 66 const char *backend = (const char *)test_data; 67 int alarm_count=0, info_count=0; 68 struct tevent_fd *fde; 69#ifdef SA_RESTART 70 struct tevent_signal *se1 = NULL; 71#endif 72 struct tevent_signal *se2 = NULL; 73#ifdef SA_SIGINFO 74 struct tevent_signal *se3 = NULL; 75#endif 76 int finished=0; 77 struct timeval t; 78 char c = 0; 79 80 ev_ctx = event_context_init_byname(test, backend); 81 if (ev_ctx == NULL) { 82 torture_comment(test, "event backend '%s' not supported\n", backend); 83 return true; 84 } 85 86 torture_comment(test, "Testing event backend '%s'\n", backend); 87 88 /* reset globals */ 89 fde_count = 0; 90 91 /* create a pipe */ 92 pipe(fd); 93 94 fde = event_add_fd(ev_ctx, ev_ctx, fd[0], EVENT_FD_READ, 95 fde_handler, fd); 96 tevent_fd_set_auto_close(fde); 97 98 event_add_timed(ev_ctx, ev_ctx, timeval_current_ofs(2,0), 99 finished_handler, &finished); 100 101#ifdef SA_RESTART 102 se1 = event_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count); 103#endif 104 se2 = event_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count); 105#ifdef SA_SIGINFO 106 se3 = event_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count); 107#endif 108 109 write(fd[1], &c, 1); 110 111 t = timeval_current(); 112 while (!finished) { 113 errno = 0; 114 if (event_loop_once(ev_ctx) == -1) { 115 talloc_free(ev_ctx); 116 torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno))); 117 } 118 } 119 120 talloc_free(fde); 121 close(fd[1]); 122 123 while (alarm_count < fde_count+1) { 124 if (event_loop_once(ev_ctx) == -1) { 125 break; 126 } 127 } 128 129 torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t)); 130 131#ifdef SA_RESTART 132 talloc_free(se1); 133#endif 134 135 torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch"); 136 137#ifdef SA_SIGINFO 138 talloc_free(se3); 139 torture_assert_int_equal(test, info_count, fde_count, "info count mismatch"); 140#endif 141 142 talloc_free(ev_ctx); 143 144 return true; 145} 146 147struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) 148{ 149 struct torture_suite *suite = torture_suite_create(mem_ctx, "EVENT"); 150 const char **list = event_backend_list(suite); 151 int i; 152 153 for (i=0;list && list[i];i++) { 154 torture_suite_add_simple_tcase_const(suite, list[i], 155 test_event_context, 156 (const void *)list[i]); 157 } 158 159 return suite; 160} 161