2 Unix SMB/CIFS implementation.
4 testing of the events subsystem
6 Copyright (C) Stefan Metzmacher 2006-2009
7 Copyright (C) Jeremy Allison 2013
9 ** NOTE! The following LGPL license applies to the tevent
10 ** library. This does NOT imply that all of Samba is released
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 3 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 #include "lib/tevent/tevent.h"
29 #include "system/filesys.h"
30 #include "system/select.h"
31 #include "torture/torture.h"
38 static int fde_wcount;
40 static void fde_handler_readwrite(struct tevent_context *ev_ctx, struct tevent_fd *f,
41 uint16_t flags, void *private_data)
43 int *fd = (int *)private_data;
46 kill(getpid(), SIGUSR1);
48 kill(getpid(), SIGALRM);
50 if ((flags & TEVENT_FD_WRITE) && (fde_wcount - fde_count < 256)) {
51 /* Don't fill the pipe and block... */
60 static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
61 struct timeval tval, void *private_data)
63 int *finished = (int *)private_data;
67 static void count_handler(struct tevent_context *ev_ctx, struct tevent_signal *te,
68 int signum, int count, void *info, void *private_data)
70 int *countp = (int *)private_data;
74 static bool test_event_context(struct torture_context *test,
75 const void *test_data)
77 struct tevent_context *ev_ctx;
78 int fd[2] = { -1, -1 };
79 const char *backend = (const char *)test_data;
80 int alarm_count=0, info_count=0;
81 struct tevent_fd *fde_read;
82 struct tevent_fd *fde_read_1;
83 struct tevent_fd *fde_write;
84 struct tevent_fd *fde_write_1;
86 struct tevent_signal *se1 = NULL;
89 struct tevent_signal *se2 = NULL;
92 struct tevent_signal *se3 = NULL;
97 ev_ctx = tevent_context_init_byname(test, backend);
99 torture_comment(test, "event backend '%s' not supported\n", backend);
103 torture_comment(test, "backend '%s' - %s\n",
104 backend, __FUNCTION__);
113 fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
114 fde_handler_readwrite, fd);
115 fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
116 fde_handler_readwrite, fd);
118 fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
119 fde_handler_readwrite, fd);
120 fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
121 fde_handler_readwrite, fd);
123 tevent_fd_set_auto_close(fde_read);
124 tevent_fd_set_auto_close(fde_write);
126 tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0),
127 finished_handler, &finished);
130 se1 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
133 se2 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
136 se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
139 t = timeval_current();
142 if (tevent_loop_once(ev_ctx) == -1) {
144 torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
148 talloc_free(fde_read);
149 talloc_free(fde_write);
150 talloc_free(fde_read_1);
151 talloc_free(fde_write_1);
153 while (alarm_count < fde_count+1) {
154 if (tevent_loop_once(ev_ctx) == -1) {
159 torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
165 torture_assert_int_equal(test, alarm_count, 1+fde_count+fde_wcount, "alarm count mismatch");
173 torture_assert_int_equal(test, info_count, fde_count+fde_wcount, "info count mismatch");
183 static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
184 static bool do_shutdown = false;
186 static void test_event_threaded_lock(void)
189 ret = pthread_mutex_lock(&threaded_mutex);
193 static void test_event_threaded_unlock(void)
196 ret = pthread_mutex_unlock(&threaded_mutex);
200 static void test_event_threaded_trace(enum tevent_trace_point point,
204 case TEVENT_TRACE_BEFORE_WAIT:
205 test_event_threaded_unlock();
207 case TEVENT_TRACE_AFTER_WAIT:
208 test_event_threaded_lock();
213 static void test_event_threaded_timer(struct tevent_context *ev,
214 struct tevent_timer *te,
215 struct timeval current_time,
221 static void *test_event_poll_thread(void *private_data)
223 struct tevent_context *ev = (struct tevent_context *)private_data;
225 test_event_threaded_lock();
229 ret = tevent_loop_once(ev);
232 test_event_threaded_unlock();
239 static void test_event_threaded_read_handler(struct tevent_context *ev,
240 struct tevent_fd *fde,
244 int *pfd = (int *)private_data;
248 if ((flags & TEVENT_FD_READ) == 0) {
253 nread = read(*pfd, &c, 1);
254 } while ((nread == -1) && (errno == EINTR));
259 static bool test_event_context_threaded(struct torture_context *test,
260 const void *test_data)
262 struct tevent_context *ev;
263 struct tevent_timer *te;
264 struct tevent_fd *fde;
265 pthread_t poll_thread;
270 ev = tevent_context_init_byname(test, "poll_mt");
271 torture_assert(test, ev != NULL, "poll_mt not supported");
273 tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
275 te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
276 test_event_threaded_timer, NULL);
277 torture_assert(test, te != NULL, "Could not add timer");
279 ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
280 torture_assert(test, ret == 0, "Could not create poll thread");
283 torture_assert(test, ret == 0, "Could not create pipe");
287 test_event_threaded_lock();
289 fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
290 test_event_threaded_read_handler, &fds[0]);
291 torture_assert(test, fde != NULL, "Could not add fd event");
293 test_event_threaded_unlock();
297 write(fds[1], &c, 1);
301 test_event_threaded_lock();
303 test_event_threaded_unlock();
305 write(fds[1], &c, 1);
307 ret = pthread_join(poll_thread, NULL);
308 torture_assert(test, ret == 0, "pthread_join failed");
315 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
317 struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
318 const char **list = tevent_backend_list(suite);
321 for (i=0;list && list[i];i++) {
322 torture_suite_add_simple_tcase_const(suite, list[i],
324 (const void *)list[i]);
328 torture_suite_add_simple_tcase_const(suite, "poll_mt_threaded",
329 test_event_context_threaded,