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 "system/network.h"
32 #include "torture/torture.h"
40 static void fde_handler_read(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);
54 static void fde_handler_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
55 uint16_t flags, void *private_data)
57 int *fd = (int *)private_data;
63 /* These should never fire... */
64 static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
65 uint16_t flags, void *private_data)
67 struct torture_context *test = (struct torture_context *)private_data;
68 torture_comment(test, "fde_handler_read_1 should never fire !\n");
72 /* These should never fire... */
73 static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
74 uint16_t flags, void *private_data)
76 struct torture_context *test = (struct torture_context *)private_data;
77 torture_comment(test, "fde_handler_write_1 should never fire !\n");
81 static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
82 struct timeval tval, void *private_data)
84 int *finished = (int *)private_data;
88 static void count_handler(struct tevent_context *ev_ctx, struct tevent_signal *te,
89 int signum, int count, void *info, void *private_data)
91 int *countp = (int *)private_data;
95 static bool test_event_context(struct torture_context *test,
96 const void *test_data)
98 struct tevent_context *ev_ctx;
99 int fd[2] = { -1, -1 };
100 const char *backend = (const char *)test_data;
101 int alarm_count=0, info_count=0;
102 struct tevent_fd *fde_read;
103 struct tevent_fd *fde_read_1;
104 struct tevent_fd *fde_write;
105 struct tevent_fd *fde_write_1;
107 struct tevent_signal *se1 = NULL;
110 struct tevent_signal *se2 = NULL;
113 struct tevent_signal *se3 = NULL;
118 ev_ctx = tevent_context_init_byname(test, backend);
119 if (ev_ctx == NULL) {
120 torture_comment(test, "event backend '%s' not supported\n", backend);
124 torture_comment(test, "backend '%s' - %s\n",
125 backend, __FUNCTION__);
133 fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
134 fde_handler_read, fd);
135 fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
136 fde_handler_write_1, test);
138 fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
139 fde_handler_write, fd);
140 fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
141 fde_handler_read_1, test);
143 tevent_fd_set_auto_close(fde_read);
144 tevent_fd_set_auto_close(fde_write);
146 tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0),
147 finished_handler, &finished);
150 se1 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
151 torture_assert(test, se1 != NULL, "failed to setup se1");
154 se2 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
155 torture_assert(test, se2 != NULL, "failed to setup se2");
158 se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
159 torture_assert(test, se3 != NULL, "failed to setup se3");
162 t = timeval_current();
165 if (tevent_loop_once(ev_ctx) == -1) {
167 torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
171 talloc_free(fde_read);
172 talloc_free(fde_write);
173 talloc_free(fde_read_1);
174 talloc_free(fde_write_1);
176 while (alarm_count < fde_count+1) {
177 if (tevent_loop_once(ev_ctx) == -1) {
182 torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
188 torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
192 * we do not call talloc_free(se2)
193 * because it is already gone,
194 * after triggering the event handler.
200 torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
208 struct test_event_fd1_state {
209 struct torture_context *tctx;
211 struct tevent_context *ev;
213 struct tevent_timer *te;
214 struct tevent_fd *fde0;
215 struct tevent_fd *fde1;
225 static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx,
226 struct tevent_fd *fde,
230 struct test_event_fd1_state *state =
231 (struct test_event_fd1_state *)private_data;
233 if (state->drain_done) {
234 state->finished = true;
235 state->error = __location__;
243 if (!(flags & TEVENT_FD_READ)) {
244 state->finished = true;
245 state->error = __location__;
249 ret = read(state->sock[0], &c, 1);
257 tevent_fd_set_flags(fde, 0);
258 state->drain_done = true;
262 if (!state->got_write) {
265 if (flags != TEVENT_FD_WRITE) {
266 state->finished = true;
267 state->error = __location__;
270 state->got_write = true;
273 * we write to the other socket...
275 write(state->sock[1], &c, 1);
276 TEVENT_FD_NOT_WRITEABLE(fde);
277 TEVENT_FD_READABLE(fde);
281 if (!state->got_read) {
282 if (flags != TEVENT_FD_READ) {
283 state->finished = true;
284 state->error = __location__;
287 state->got_read = true;
289 TEVENT_FD_NOT_READABLE(fde);
293 state->finished = true;
294 state->error = __location__;
298 static void test_event_fd1_finished(struct tevent_context *ev_ctx,
299 struct tevent_timer *te,
303 struct test_event_fd1_state *state =
304 (struct test_event_fd1_state *)private_data;
306 if (state->drain_done) {
307 state->finished = true;
311 if (!state->got_write) {
312 state->finished = true;
313 state->error = __location__;
317 if (!state->got_read) {
318 state->finished = true;
319 state->error = __location__;
324 if (state->loop_count > 3) {
325 state->finished = true;
326 state->error = __location__;
330 state->got_write = false;
331 state->got_read = false;
333 tevent_fd_set_flags(state->fde0, TEVENT_FD_WRITE);
335 if (state->loop_count > 2) {
337 TALLOC_FREE(state->fde1);
338 TEVENT_FD_READABLE(state->fde0);
341 state->te = tevent_add_timer(state->ev, state->ev,
342 timeval_current_ofs(0,2000),
343 test_event_fd1_finished, state);
346 static bool test_event_fd1(struct torture_context *tctx,
347 const void *test_data)
349 struct test_event_fd1_state state;
353 state.backend = (const char *)test_data;
355 state.ev = tevent_context_init_byname(tctx, state.backend);
356 if (state.ev == NULL) {
357 torture_skip(tctx, talloc_asprintf(tctx,
358 "event backend '%s' not supported\n",
363 tevent_set_debug_stderr(state.ev);
364 torture_comment(tctx, "backend '%s' - %s\n",
365 state.backend, __FUNCTION__);
368 * This tests the following:
370 * It monitors the state of state.sock[0]
371 * with tevent_fd, but we never read/write on state.sock[0]
372 * while state.sock[1] * is only used to write a few bytes.
375 * - we wait only for TEVENT_FD_WRITE on state.sock[0]
376 * - we write 1 byte to state.sock[1]
377 * - we wait only for TEVENT_FD_READ on state.sock[0]
378 * - we disable events on state.sock[0]
379 * - the timer event restarts the loop
380 * Then we close state.sock[1]
382 * - we wait for TEVENT_FD_READ/WRITE on state.sock[0]
383 * - we try to read 1 byte
384 * - if the read gets an error of returns 0
385 * we disable the event handler
386 * - the timer finishes the test
390 socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock);
392 state.te = tevent_add_timer(state.ev, state.ev,
393 timeval_current_ofs(0,1000),
394 test_event_fd1_finished, &state);
395 state.fde0 = tevent_add_fd(state.ev, state.ev,
396 state.sock[0], TEVENT_FD_WRITE,
397 test_event_fd1_fde_handler, &state);
398 /* state.fde1 is only used to auto close */
399 state.fde1 = tevent_add_fd(state.ev, state.ev,
401 test_event_fd1_fde_handler, &state);
403 tevent_fd_set_auto_close(state.fde0);
404 tevent_fd_set_auto_close(state.fde1);
406 while (!state.finished) {
408 if (tevent_loop_once(state.ev) == -1) {
409 talloc_free(state.ev);
410 torture_fail(tctx, talloc_asprintf(tctx,
411 "Failed event loop %s\n",
416 talloc_free(state.ev);
418 torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
426 static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
427 static bool do_shutdown = false;
429 static void test_event_threaded_lock(void)
432 ret = pthread_mutex_lock(&threaded_mutex);
436 static void test_event_threaded_unlock(void)
439 ret = pthread_mutex_unlock(&threaded_mutex);
443 static void test_event_threaded_trace(enum tevent_trace_point point,
447 case TEVENT_TRACE_BEFORE_WAIT:
448 test_event_threaded_unlock();
450 case TEVENT_TRACE_AFTER_WAIT:
451 test_event_threaded_lock();
453 case TEVENT_TRACE_BEFORE_LOOP_ONCE:
454 case TEVENT_TRACE_AFTER_LOOP_ONCE:
459 static void test_event_threaded_timer(struct tevent_context *ev,
460 struct tevent_timer *te,
461 struct timeval current_time,
467 static void *test_event_poll_thread(void *private_data)
469 struct tevent_context *ev = (struct tevent_context *)private_data;
471 test_event_threaded_lock();
475 ret = tevent_loop_once(ev);
478 test_event_threaded_unlock();
485 static void test_event_threaded_read_handler(struct tevent_context *ev,
486 struct tevent_fd *fde,
490 int *pfd = (int *)private_data;
494 if ((flags & TEVENT_FD_READ) == 0) {
499 nread = read(*pfd, &c, 1);
500 } while ((nread == -1) && (errno == EINTR));
505 static bool test_event_context_threaded(struct torture_context *test,
506 const void *test_data)
508 struct tevent_context *ev;
509 struct tevent_timer *te;
510 struct tevent_fd *fde;
511 pthread_t poll_thread;
516 ev = tevent_context_init_byname(test, "poll_mt");
517 torture_assert(test, ev != NULL, "poll_mt not supported");
519 tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
521 te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
522 test_event_threaded_timer, NULL);
523 torture_assert(test, te != NULL, "Could not add timer");
525 ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
526 torture_assert(test, ret == 0, "Could not create poll thread");
529 torture_assert(test, ret == 0, "Could not create pipe");
533 test_event_threaded_lock();
535 fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
536 test_event_threaded_read_handler, &fds[0]);
537 torture_assert(test, fde != NULL, "Could not add fd event");
539 test_event_threaded_unlock();
543 write(fds[1], &c, 1);
547 test_event_threaded_lock();
549 test_event_threaded_unlock();
551 write(fds[1], &c, 1);
553 ret = pthread_join(poll_thread, NULL);
554 torture_assert(test, ret == 0, "pthread_join failed");
561 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
563 struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
564 const char **list = tevent_backend_list(suite);
567 for (i=0;list && list[i];i++) {
568 struct torture_suite *backend_suite;
570 backend_suite = torture_suite_create(mem_ctx, list[i]);
572 torture_suite_add_simple_tcase_const(backend_suite,
575 (const void *)list[i]);
576 torture_suite_add_simple_tcase_const(backend_suite,
579 (const void *)list[i]);
581 torture_suite_add_suite(suite, backend_suite);
585 torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt",
586 test_event_context_threaded,