tevent: release 0.16.1
[Samba.git] / lib / tevent / testsuite.c
blobe088166175647f9dcd0cec89377d0a175948c50c
1 /*
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
11 ** under the LGPL
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/>.
27 #include "includes.h"
28 #define TEVENT_DEPRECATED 1
29 #include "tevent.h"
30 #include "system/filesys.h"
31 #include "system/select.h"
32 #include "system/network.h"
33 #include "torture/torture.h"
34 #include "torture/local/proto.h"
35 #include "lib/util/blocking.h"
36 #ifdef HAVE_PTHREAD
37 #include "system/threads.h"
38 #include <assert.h>
39 #endif
41 static struct tevent_context *
42 test_tevent_context_init(TALLOC_CTX *mem_ctx)
44 struct tevent_context *ev = NULL;
46 ev = tevent_context_init(mem_ctx);
47 if (ev != NULL) {
48 samba_tevent_set_debug(ev, "<default>");
51 return ev;
54 static struct tevent_context *
55 test_tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name)
57 struct tevent_context *ev = NULL;
59 ev = tevent_context_init_byname(mem_ctx, name);
60 if (ev != NULL) {
61 samba_tevent_set_debug(ev, name);
64 return ev;
67 static int fde_count;
69 static void do_read(int fd, void *buf, size_t count)
71 ssize_t ret;
73 do {
74 ret = read(fd, buf, count);
75 } while (ret == -1 && errno == EINTR);
78 static void fde_handler_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
79 uint16_t flags, void *private_data)
81 int *fd = (int *)private_data;
82 char c;
83 #ifdef SA_SIGINFO
84 kill(getpid(), SIGUSR1);
85 #endif
86 kill(getpid(), SIGALRM);
88 do_read(fd[0], &c, 1);
89 fde_count++;
92 static void do_write(int fd, void *buf, size_t count)
94 ssize_t ret;
96 do {
97 ret = write(fd, buf, count);
98 } while (ret == -1 && errno == EINTR);
101 static void do_fill(int fd)
103 uint8_t buf[1024] = {0, };
104 ssize_t ret;
106 set_blocking(fd, false);
108 do {
109 do {
110 ret = write(fd, buf, ARRAY_SIZE(buf));
111 } while (ret == -1 && errno == EINTR);
112 } while (ret == ARRAY_SIZE(buf));
114 set_blocking(fd, true);
117 static void fde_handler_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
118 uint16_t flags, void *private_data)
120 int *fd = (int *)private_data;
121 char c = 0;
123 do_write(fd[1], &c, 1);
127 /* This will only fire if the fd's returned from pipe() are bi-directional. */
128 static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
129 uint16_t flags, void *private_data)
131 int *fd = (int *)private_data;
132 char c;
133 #ifdef SA_SIGINFO
134 kill(getpid(), SIGUSR1);
135 #endif
136 kill(getpid(), SIGALRM);
138 do_read(fd[1], &c, 1);
139 fde_count++;
142 /* This will only fire if the fd's returned from pipe() are bi-directional. */
143 static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
144 uint16_t flags, void *private_data)
146 int *fd = (int *)private_data;
147 char c = 0;
148 do_write(fd[0], &c, 1);
151 static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
152 struct timeval tval, void *private_data)
154 int *finished = (int *)private_data;
155 (*finished) = 1;
158 static void count_handler(struct tevent_context *ev_ctx, struct tevent_signal *te,
159 int signum, int count, void *info, void *private_data)
161 int *countp = (int *)private_data;
162 (*countp) += count;
165 static bool test_event_context(struct torture_context *test,
166 const void *test_data)
168 struct tevent_context *ev_ctx;
169 int fd[2] = { -1, -1 };
170 const char *backend = (const char *)test_data;
171 int alarm_count=0, info_count=0;
172 struct tevent_fd *fde_read;
173 struct tevent_fd *fde_read_1;
174 struct tevent_fd *fde_write;
175 struct tevent_fd *fde_write_1;
176 #ifdef SA_RESTART
177 struct tevent_signal *se1 = NULL;
178 #endif
179 #ifdef SA_RESETHAND
180 struct tevent_signal *se2 = NULL;
181 #endif
182 #ifdef SA_SIGINFO
183 struct tevent_signal *se3 = NULL;
184 #endif
185 int finished=0;
186 struct timeval t;
187 int ret;
189 ev_ctx = test_tevent_context_init_byname(test, backend);
190 if (ev_ctx == NULL) {
191 torture_comment(test, "event backend '%s' not supported\n", backend);
192 return true;
195 torture_comment(test, "backend '%s' - %s\n",
196 backend, __FUNCTION__);
198 /* reset globals */
199 fde_count = 0;
201 /* create a pipe */
202 ret = pipe(fd);
203 torture_assert_int_equal(test, ret, 0, "pipe failed");
205 fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
206 fde_handler_read, fd);
207 fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
208 fde_handler_write_1, fd);
210 fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
211 fde_handler_write, fd);
212 fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
213 fde_handler_read_1, fd);
215 tevent_fd_set_auto_close(fde_read);
216 tevent_fd_set_auto_close(fde_write);
218 tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0),
219 finished_handler, &finished);
221 #ifdef SA_RESTART
222 se1 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
223 torture_assert(test, se1 != NULL, "failed to setup se1");
224 #endif
225 #ifdef SA_RESETHAND
226 se2 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
227 torture_assert(test, se2 != NULL, "failed to setup se2");
228 #endif
229 #ifdef SA_SIGINFO
230 se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
231 torture_assert(test, se3 != NULL, "failed to setup se3");
232 #endif
234 t = timeval_current();
235 while (!finished) {
236 errno = 0;
237 if (tevent_loop_once(ev_ctx) == -1) {
238 TALLOC_FREE(ev_ctx);
239 torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
240 return false;
244 talloc_free(fde_read_1);
245 talloc_free(fde_write_1);
246 talloc_free(fde_read);
247 talloc_free(fde_write);
249 while (alarm_count < fde_count+1) {
250 if (tevent_loop_once(ev_ctx) == -1) {
251 break;
255 torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
257 #ifdef SA_RESTART
258 talloc_free(se1);
259 #endif
261 torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
263 #ifdef SA_RESETHAND
265 * we do not call talloc_free(se2)
266 * because it is already gone,
267 * after triggering the event handler.
269 #endif
271 #ifdef SA_SIGINFO
272 talloc_free(se3);
273 torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
274 #endif
276 talloc_free(ev_ctx);
278 return true;
281 static void fde_handler_do_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
282 uint16_t flags, void *private_data)
284 int *fd = (int *)private_data;
285 char c = 0;
287 do_read(fd[0], &c, 1);
288 fde_count++;
291 static void fde_handler_do_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
292 uint16_t flags, void *private_data)
294 int *fd = (int *)private_data;
295 char c = 0;
297 do_write(fd[1], &c, 1);
300 static void fde_handler_ignore(struct tevent_context *ev_ctx, struct tevent_fd *f,
301 uint16_t flags, void *private_data)
305 static bool test_fd_speedX(struct torture_context *test,
306 const void *test_data,
307 size_t additional_fdes)
309 struct tevent_context *ev_ctx = NULL;
310 int fd[2] = { -1, -1 };
311 const char *backend = (const char *)test_data;
312 struct tevent_fd *fde_read = NULL;
313 struct tevent_fd *fde_write = NULL;
314 int finished=0;
315 struct timeval t;
316 size_t i;
317 int ret;
319 ev_ctx = test_tevent_context_init_byname(test, backend);
320 if (ev_ctx == NULL) {
321 torture_comment(test, "event backend '%s' not supported\n", backend);
322 return true;
325 torture_comment(test, "backend '%s' - test_fd_speed%zu\n",
326 backend, 1 + additional_fdes);
328 /* reset globals */
329 fde_count = 0;
331 /* create a pipe */
332 ret = pipe(fd);
333 torture_assert_int_equal(test, ret, 0, "pipe failed");
335 fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
336 fde_handler_do_read, fd);
338 fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
339 fde_handler_do_write, fd);
341 for (i = 0; i < additional_fdes; i++) {
342 tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
343 fde_handler_ignore, fd);
344 tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
345 fde_handler_ignore, fd);
348 tevent_fd_set_auto_close(fde_read);
349 tevent_fd_set_auto_close(fde_write);
351 tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(600,0),
352 finished_handler, &finished);
354 t = timeval_current();
355 while (!finished && fde_count < 1000000) {
356 errno = 0;
357 if (tevent_loop_once(ev_ctx) == -1) {
358 TALLOC_FREE(ev_ctx);
359 torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
360 return false;
364 talloc_free(fde_read);
365 talloc_free(fde_write);
367 torture_comment(test, "Got %.2f pipe events\n", (double)fde_count);
368 torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
370 talloc_free(ev_ctx);
372 return true;
375 static bool test_fd_speed1(struct torture_context *test,
376 const void *test_data)
378 return test_fd_speedX(test, test_data, 0);
381 static bool test_fd_speed2(struct torture_context *test,
382 const void *test_data)
384 return test_fd_speedX(test, test_data, 1);
387 static bool test_fd_speed3(struct torture_context *test,
388 const void *test_data)
390 return test_fd_speedX(test, test_data, 2);
393 struct test_event_fd1_state {
394 struct torture_context *tctx;
395 const char *backend;
396 struct tevent_context *ev;
397 int sock[2];
398 struct tevent_timer *te;
399 struct tevent_fd *fde0;
400 struct tevent_fd *fde1;
401 bool got_write;
402 bool got_read;
403 bool drain;
404 bool drain_done;
405 unsigned loop_count;
406 bool finished;
407 const char *error;
410 static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx,
411 struct tevent_fd *fde,
412 uint16_t flags,
413 void *private_data)
415 struct test_event_fd1_state *state =
416 (struct test_event_fd1_state *)private_data;
418 if (state->drain_done) {
419 state->finished = true;
420 state->error = __location__;
421 return;
424 if (state->drain) {
425 ssize_t ret;
426 uint8_t c = 0;
428 if (!(flags & TEVENT_FD_READ)) {
429 state->finished = true;
430 state->error = __location__;
431 return;
434 ret = read(state->sock[0], &c, 1);
435 if (ret == 1) {
436 return;
440 * end of test...
442 tevent_fd_set_flags(fde, 0);
443 state->drain_done = true;
444 return;
447 if (!state->got_write) {
448 uint8_t c = 0;
450 if (flags != TEVENT_FD_WRITE) {
451 state->finished = true;
452 state->error = __location__;
453 return;
455 state->got_write = true;
458 * we write to the other socket...
460 do_write(state->sock[1], &c, 1);
461 TEVENT_FD_NOT_WRITEABLE(fde);
462 TEVENT_FD_READABLE(fde);
463 return;
466 if (!state->got_read) {
467 if (flags != TEVENT_FD_READ) {
468 state->finished = true;
469 state->error = __location__;
470 return;
472 state->got_read = true;
474 TEVENT_FD_NOT_READABLE(fde);
475 return;
478 state->finished = true;
479 state->error = __location__;
480 return;
483 static void test_event_fd1_finished(struct tevent_context *ev_ctx,
484 struct tevent_timer *te,
485 struct timeval tval,
486 void *private_data)
488 struct test_event_fd1_state *state =
489 (struct test_event_fd1_state *)private_data;
491 if (state->drain_done) {
492 state->finished = true;
493 return;
496 if (!state->got_write) {
497 state->finished = true;
498 state->error = __location__;
499 return;
502 if (!state->got_read) {
503 state->finished = true;
504 state->error = __location__;
505 return;
508 state->loop_count++;
509 if (state->loop_count > 3) {
510 state->finished = true;
511 state->error = __location__;
512 return;
515 state->got_write = false;
516 state->got_read = false;
518 tevent_fd_set_flags(state->fde0, TEVENT_FD_WRITE);
520 if (state->loop_count > 2) {
521 state->drain = true;
522 TALLOC_FREE(state->fde1);
523 TEVENT_FD_READABLE(state->fde0);
526 state->te = tevent_add_timer(state->ev, state->ev,
527 timeval_current_ofs(0,2000),
528 test_event_fd1_finished, state);
531 static bool test_event_fd1(struct torture_context *tctx,
532 const void *test_data)
534 struct test_event_fd1_state state;
535 int ret;
537 ZERO_STRUCT(state);
538 state.tctx = tctx;
539 state.backend = (const char *)test_data;
541 state.ev = test_tevent_context_init_byname(tctx, state.backend);
542 if (state.ev == NULL) {
543 torture_skip(tctx, talloc_asprintf(tctx,
544 "event backend '%s' not supported\n",
545 state.backend));
546 return true;
549 torture_comment(tctx, "backend '%s' - %s\n",
550 state.backend, __FUNCTION__);
553 * This tests the following:
555 * It monitors the state of state.sock[0]
556 * with tevent_fd, but we never read/write on state.sock[0]
557 * while state.sock[1] * is only used to write a few bytes.
559 * We have a loop:
560 * - we wait only for TEVENT_FD_WRITE on state.sock[0]
561 * - we write 1 byte to state.sock[1]
562 * - we wait only for TEVENT_FD_READ on state.sock[0]
563 * - we disable events on state.sock[0]
564 * - the timer event restarts the loop
565 * Then we close state.sock[1]
566 * We have a loop:
567 * - we wait for TEVENT_FD_READ/WRITE on state.sock[0]
568 * - we try to read 1 byte
569 * - if the read gets an error of returns 0
570 * we disable the event handler
571 * - the timer finishes the test
573 state.sock[0] = -1;
574 state.sock[1] = -1;
576 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock);
577 torture_assert(tctx, ret == 0, "socketpair() failed");
579 state.te = tevent_add_timer(state.ev, state.ev,
580 timeval_current_ofs(0,10000),
581 test_event_fd1_finished, &state);
582 state.fde0 = tevent_add_fd(state.ev, state.ev,
583 state.sock[0], TEVENT_FD_WRITE,
584 test_event_fd1_fde_handler, &state);
585 /* state.fde1 is only used to auto close */
586 state.fde1 = tevent_add_fd(state.ev, state.ev,
587 state.sock[1], 0,
588 test_event_fd1_fde_handler, &state);
590 tevent_fd_set_auto_close(state.fde0);
591 tevent_fd_set_auto_close(state.fde1);
593 while (!state.finished) {
594 errno = 0;
595 if (tevent_loop_once(state.ev) == -1) {
596 talloc_free(state.ev);
597 torture_fail(tctx, talloc_asprintf(tctx,
598 "Failed event loop %s\n",
599 strerror(errno)));
603 talloc_free(state.ev);
605 torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
606 "%s", state.error));
608 return true;
611 struct test_event_fd2_state {
612 struct torture_context *tctx;
613 const char *backend;
614 struct tevent_context *ev;
615 struct tevent_timer *te;
616 struct test_event_fd2_sock {
617 struct test_event_fd2_state *state;
618 int fd;
619 struct tevent_fd *fde;
620 size_t num_written;
621 size_t num_read;
622 bool got_full;
623 } sock0, sock1;
624 bool finished;
625 const char *error;
628 static void test_event_fd2_sock_handler(struct tevent_context *ev_ctx,
629 struct tevent_fd *fde,
630 uint16_t flags,
631 void *private_data)
633 struct test_event_fd2_sock *cur_sock =
634 (struct test_event_fd2_sock *)private_data;
635 struct test_event_fd2_state *state = cur_sock->state;
636 struct test_event_fd2_sock *oth_sock = NULL;
637 uint8_t v = 0, c;
638 ssize_t ret;
640 if (cur_sock == &state->sock0) {
641 oth_sock = &state->sock1;
642 } else {
643 oth_sock = &state->sock0;
646 if (oth_sock->num_written == 1) {
647 if (flags != (TEVENT_FD_READ | TEVENT_FD_WRITE)) {
648 state->finished = true;
649 state->error = __location__;
650 return;
654 if (cur_sock->num_read == oth_sock->num_written) {
655 state->finished = true;
656 state->error = __location__;
657 return;
660 if (!(flags & TEVENT_FD_READ)) {
661 state->finished = true;
662 state->error = __location__;
663 return;
666 if (oth_sock->num_read >= PIPE_BUF) {
668 * On Linux we become writable once we've read
669 * one byte. On Solaris we only become writable
670 * again once we've read 4096 bytes. PIPE_BUF
671 * is probably a safe bet to test against.
673 * There should be room to write a byte again
675 if (!(flags & TEVENT_FD_WRITE)) {
676 state->finished = true;
677 state->error = __location__;
678 return;
682 if ((flags & TEVENT_FD_WRITE) && !cur_sock->got_full) {
683 v = (uint8_t)cur_sock->num_written;
684 ret = write(cur_sock->fd, &v, 1);
685 if (ret != 1) {
686 state->finished = true;
687 state->error = __location__;
688 return;
690 cur_sock->num_written++;
691 if (cur_sock->num_written > 0x80000000) {
692 state->finished = true;
693 state->error = __location__;
694 return;
696 return;
699 if (!cur_sock->got_full) {
700 cur_sock->got_full = true;
702 if (!oth_sock->got_full) {
704 * cur_sock is full,
705 * lets wait for oth_sock
706 * to be filled
708 tevent_fd_set_flags(cur_sock->fde, 0);
709 return;
713 * oth_sock waited for cur_sock,
714 * lets restart it
716 tevent_fd_set_flags(oth_sock->fde,
717 TEVENT_FD_READ|TEVENT_FD_WRITE);
720 ret = read(cur_sock->fd, &v, 1);
721 if (ret != 1) {
722 state->finished = true;
723 state->error = __location__;
724 return;
726 c = (uint8_t)cur_sock->num_read;
727 if (c != v) {
728 state->finished = true;
729 state->error = __location__;
730 return;
732 cur_sock->num_read++;
734 if (cur_sock->num_read < oth_sock->num_written) {
735 /* there is more to read */
736 return;
739 * we read everything, we need to remove TEVENT_FD_WRITE
740 * to avoid spinning
742 TEVENT_FD_NOT_WRITEABLE(cur_sock->fde);
744 if (oth_sock->num_read == cur_sock->num_written) {
746 * both directions are finished
748 state->finished = true;
751 return;
754 static void test_event_fd2_finished(struct tevent_context *ev_ctx,
755 struct tevent_timer *te,
756 struct timeval tval,
757 void *private_data)
759 struct test_event_fd2_state *state =
760 (struct test_event_fd2_state *)private_data;
763 * this should never be triggered
765 state->finished = true;
766 state->error = __location__;
769 static bool test_event_fd2(struct torture_context *tctx,
770 const void *test_data)
772 struct test_event_fd2_state state;
773 int sock[2];
774 uint8_t c = 0;
776 ZERO_STRUCT(state);
777 state.tctx = tctx;
778 state.backend = (const char *)test_data;
780 state.ev = test_tevent_context_init_byname(tctx, state.backend);
781 if (state.ev == NULL) {
782 torture_skip(tctx, talloc_asprintf(tctx,
783 "event backend '%s' not supported\n",
784 state.backend));
785 return true;
788 torture_comment(tctx, "backend '%s' - %s\n",
789 state.backend, __FUNCTION__);
792 * This tests the following
794 * - We write 1 byte to each socket
795 * - We wait for TEVENT_FD_READ/WRITE on both sockets
796 * - When we get TEVENT_FD_WRITE we write 1 byte
797 * until both socket buffers are full, which
798 * means both sockets only get TEVENT_FD_READ.
799 * - Then we read 1 byte until we have consumed
800 * all bytes the other end has written.
802 sock[0] = -1;
803 sock[1] = -1;
804 socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
807 * the timer should never expire
809 state.te = tevent_add_timer(state.ev, state.ev,
810 timeval_current_ofs(600, 0),
811 test_event_fd2_finished, &state);
812 state.sock0.state = &state;
813 state.sock0.fd = sock[0];
814 state.sock0.fde = tevent_add_fd(state.ev, state.ev,
815 state.sock0.fd,
816 TEVENT_FD_READ | TEVENT_FD_WRITE,
817 test_event_fd2_sock_handler,
818 &state.sock0);
819 state.sock1.state = &state;
820 state.sock1.fd = sock[1];
821 state.sock1.fde = tevent_add_fd(state.ev, state.ev,
822 state.sock1.fd,
823 TEVENT_FD_READ | TEVENT_FD_WRITE,
824 test_event_fd2_sock_handler,
825 &state.sock1);
827 tevent_fd_set_auto_close(state.sock0.fde);
828 tevent_fd_set_auto_close(state.sock1.fde);
830 do_write(state.sock0.fd, &c, 1);
831 state.sock0.num_written++;
832 do_write(state.sock1.fd, &c, 1);
833 state.sock1.num_written++;
835 while (!state.finished) {
836 errno = 0;
837 if (tevent_loop_once(state.ev) == -1) {
838 talloc_free(state.ev);
839 torture_fail(tctx, talloc_asprintf(tctx,
840 "Failed event loop %s\n",
841 strerror(errno)));
845 talloc_free(state.ev);
847 torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
848 "%s", state.error));
850 return true;
853 struct test_event_fd3_state {
854 struct torture_context *tctx;
855 const char *backend;
856 struct tevent_context *ev;
857 struct timeval start_time;
858 struct tevent_timer *te1, *te2, *te3, *te4, *te5;
859 struct test_event_fd3_sock {
860 struct test_event_fd3_state *state;
861 const char *sock_name;
862 int fd;
863 const char *phase_name;
864 uint64_t iteration_id;
865 uint64_t max_iterations;
866 uint16_t expected_flags;
867 uint8_t expected_count;
868 uint8_t actual_count;
869 struct test_event_fd3_fde {
870 struct test_event_fd3_sock *sock;
871 struct tevent_fd *fde;
872 uint64_t last_iteration_id;
873 } fde1, fde2, fde3, fde4, fde5, fde6, fde7, fde8, fde9;
874 void (*fde_callback)(struct test_event_fd3_fde *tfde,
875 uint16_t flags);
876 } sock0, sock1;
877 bool finished;
878 const char *error;
881 static void test_event_fd3_fde_callback(struct test_event_fd3_fde *tfde,
882 uint16_t flags)
884 struct test_event_fd3_sock *sock = tfde->sock;
885 struct test_event_fd3_state *state = sock->state;
886 uint16_t fde_flags = tevent_fd_get_flags(tfde->fde);
887 uint16_t expected_flags = sock->expected_flags & fde_flags;
889 if (expected_flags == 0) {
890 state->finished = true;
891 state->error = __location__;
892 return;
895 if (flags != expected_flags) {
896 state->finished = true;
897 state->error = __location__;
898 return;
901 if (tfde->last_iteration_id == sock->iteration_id) {
902 state->finished = true;
903 state->error = __location__;
904 return;
907 tfde->last_iteration_id = sock->iteration_id;
909 sock->actual_count += 1;
911 if (sock->actual_count > sock->expected_count) {
912 state->finished = true;
913 state->error = __location__;
914 return;
917 if (sock->actual_count == sock->expected_count) {
918 sock->actual_count = 0;
919 sock->iteration_id += 1;
922 if (sock->iteration_id > sock->max_iterations) {
923 torture_comment(state->tctx,
924 "%s: phase[%s] finished with %"PRIu64" iterations\n",
925 sock->sock_name,
926 sock->phase_name,
927 sock->max_iterations);
928 tevent_fd_set_flags(sock->fde1.fde, 0);
929 tevent_fd_set_flags(sock->fde2.fde, 0);
930 tevent_fd_set_flags(sock->fde3.fde, 0);
931 tevent_fd_set_flags(sock->fde4.fde, 0);
932 tevent_fd_set_flags(sock->fde5.fde, 0);
933 tevent_fd_set_flags(sock->fde6.fde, 0);
934 tevent_fd_set_flags(sock->fde7.fde, 0);
935 tevent_fd_set_flags(sock->fde8.fde, 0);
936 tevent_fd_set_flags(sock->fde9.fde, 0);
937 sock->fde_callback = NULL;
941 static void test_event_fd3_prepare_phase(struct test_event_fd3_sock *sock,
942 const char *phase_name,
943 uint64_t max_iterations,
944 uint16_t expected_flags,
945 uint8_t expected_count,
946 uint16_t flags1,
947 uint16_t flags2,
948 uint16_t flags3,
949 uint16_t flags4,
950 uint16_t flags5,
951 uint16_t flags6,
952 uint16_t flags7,
953 uint16_t flags8,
954 uint16_t flags9)
956 struct test_event_fd3_state *state = sock->state;
958 if (sock->fde_callback != NULL) {
959 state->finished = true;
960 state->error = __location__;
961 return;
964 sock->phase_name = phase_name;
965 sock->max_iterations = max_iterations;
966 sock->expected_flags = expected_flags;
967 sock->expected_count = expected_count;
968 sock->iteration_id = 1;
969 sock->actual_count = 0;
971 tevent_fd_set_flags(sock->fde1.fde, flags1);
972 sock->fde1.last_iteration_id = 0;
973 tevent_fd_set_flags(sock->fde2.fde, flags2);
974 sock->fde2.last_iteration_id = 0;
975 tevent_fd_set_flags(sock->fde3.fde, flags3);
976 sock->fde3.last_iteration_id = 0;
977 tevent_fd_set_flags(sock->fde4.fde, flags4);
978 sock->fde4.last_iteration_id = 0;
979 tevent_fd_set_flags(sock->fde5.fde, flags5);
980 sock->fde5.last_iteration_id = 0;
981 tevent_fd_set_flags(sock->fde6.fde, flags6);
982 sock->fde6.last_iteration_id = 0;
983 tevent_fd_set_flags(sock->fde7.fde, flags7);
984 sock->fde7.last_iteration_id = 0;
985 tevent_fd_set_flags(sock->fde8.fde, flags8);
986 sock->fde8.last_iteration_id = 0;
987 tevent_fd_set_flags(sock->fde9.fde, flags9);
988 sock->fde9.last_iteration_id = 0;
990 sock->fde_callback = test_event_fd3_fde_callback;
993 static void test_event_fd3_sock_handler(struct tevent_context *ev_ctx,
994 struct tevent_fd *fde,
995 uint16_t flags,
996 void *private_data)
998 struct test_event_fd3_fde *tfde =
999 (struct test_event_fd3_fde *)private_data;
1000 struct test_event_fd3_sock *sock = tfde->sock;
1001 struct test_event_fd3_state *state = sock->state;
1003 if (sock->fd == -1) {
1004 state->finished = true;
1005 state->error = __location__;
1006 return;
1009 if (sock->fde_callback == NULL) {
1010 state->finished = true;
1011 state->error = __location__;
1012 return;
1015 sock->fde_callback(tfde, flags);
1016 return;
1019 static bool test_event_fd3_assert_timeout(struct test_event_fd3_state *state,
1020 double expected_elapsed,
1021 const char *func)
1023 double e = timeval_elapsed(&state->start_time);
1024 double max_latency = 0.05;
1026 if (e < expected_elapsed) {
1027 torture_comment(state->tctx,
1028 "%s: elapsed=%.6f < expected_elapsed=%.6f\n",
1029 func, e, expected_elapsed);
1030 state->finished = true;
1031 state->error = __location__;
1032 return false;
1035 if (e > (expected_elapsed + max_latency)) {
1036 torture_comment(state->tctx,
1037 "%s: elapsed=%.6f > "
1038 "(expected_elapsed=%.6f + max_latency=%.6f)\n",
1039 func, e, expected_elapsed, max_latency);
1040 state->finished = true;
1041 state->error = __location__;
1042 return false;
1045 torture_comment(state->tctx, "%s: elapsed=%.6f\n", __func__, e);
1046 return true;
1049 static void test_event_fd3_writeable(struct tevent_context *ev_ctx,
1050 struct tevent_timer *te,
1051 struct timeval tval,
1052 void *private_data)
1054 struct test_event_fd3_state *state =
1055 (struct test_event_fd3_state *)private_data;
1057 if (!test_event_fd3_assert_timeout(state, 1, __func__)) {
1058 return;
1061 test_event_fd3_prepare_phase(&state->sock0,
1062 __func__,
1063 INT8_MAX,
1064 TEVENT_FD_WRITE,
1066 TEVENT_FD_WRITE,
1068 TEVENT_FD_READ,
1069 TEVENT_FD_WRITE,
1070 TEVENT_FD_READ|TEVENT_FD_WRITE,
1071 TEVENT_FD_READ,
1072 TEVENT_FD_WRITE,
1073 TEVENT_FD_READ|TEVENT_FD_WRITE,
1076 test_event_fd3_prepare_phase(&state->sock1,
1077 __func__,
1078 INT8_MAX,
1079 TEVENT_FD_WRITE,
1081 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1082 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1083 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1084 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1085 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1086 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1087 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1088 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1089 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR);
1092 static void test_event_fd3_readable(struct tevent_context *ev_ctx,
1093 struct tevent_timer *te,
1094 struct timeval tval,
1095 void *private_data)
1097 struct test_event_fd3_state *state =
1098 (struct test_event_fd3_state *)private_data;
1099 uint8_t c = 0;
1101 if (!test_event_fd3_assert_timeout(state, 2, __func__)) {
1102 return;
1105 do_write(state->sock0.fd, &c, 1);
1106 do_write(state->sock1.fd, &c, 1);
1108 test_event_fd3_prepare_phase(&state->sock0,
1109 __func__,
1110 INT8_MAX,
1111 TEVENT_FD_READ|TEVENT_FD_WRITE,
1113 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1114 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1115 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1116 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1117 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1118 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1119 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1120 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1121 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR);
1123 test_event_fd3_prepare_phase(&state->sock1,
1124 __func__,
1125 INT8_MAX,
1126 TEVENT_FD_READ|TEVENT_FD_WRITE,
1128 TEVENT_FD_READ,
1129 TEVENT_FD_READ|TEVENT_FD_WRITE,
1130 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1132 TEVENT_FD_READ,
1133 TEVENT_FD_WRITE,
1134 TEVENT_FD_ERROR,
1135 TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1136 TEVENT_FD_READ|TEVENT_FD_WRITE);
1139 static void test_event_fd3_not_writeable(struct tevent_context *ev_ctx,
1140 struct tevent_timer *te,
1141 struct timeval tval,
1142 void *private_data)
1144 struct test_event_fd3_state *state =
1145 (struct test_event_fd3_state *)private_data;
1147 if (!test_event_fd3_assert_timeout(state, 3, __func__)) {
1148 return;
1151 do_fill(state->sock0.fd);
1152 do_fill(state->sock1.fd);
1154 test_event_fd3_prepare_phase(&state->sock0,
1155 __func__,
1156 INT8_MAX,
1157 TEVENT_FD_READ,
1159 TEVENT_FD_READ|TEVENT_FD_WRITE,
1160 TEVENT_FD_WRITE,
1161 TEVENT_FD_READ,
1163 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1164 TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1165 TEVENT_FD_READ|TEVENT_FD_ERROR,
1166 TEVENT_FD_ERROR,
1167 TEVENT_FD_READ);
1169 test_event_fd3_prepare_phase(&state->sock1,
1170 __func__,
1171 INT8_MAX,
1172 TEVENT_FD_READ,
1174 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1175 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1176 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1177 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1178 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1179 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1180 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1181 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1182 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR);
1185 static void test_event_fd3_off(struct tevent_context *ev_ctx,
1186 struct tevent_timer *te,
1187 struct timeval tval,
1188 void *private_data)
1190 struct test_event_fd3_state *state =
1191 (struct test_event_fd3_state *)private_data;
1193 if (!test_event_fd3_assert_timeout(state, 4, __func__)) {
1194 return;
1197 TALLOC_FREE(state->sock0.fde1.fde);
1198 state->sock0.fd = -1;
1200 test_event_fd3_prepare_phase(&state->sock1,
1201 __func__,
1202 INT8_MAX,
1203 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1205 TEVENT_FD_READ|TEVENT_FD_WRITE,
1206 TEVENT_FD_WRITE,
1207 TEVENT_FD_READ,
1209 TEVENT_FD_READ|TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1210 TEVENT_FD_WRITE|TEVENT_FD_ERROR,
1211 TEVENT_FD_READ|TEVENT_FD_ERROR,
1212 TEVENT_FD_ERROR,
1213 TEVENT_FD_READ);
1216 static void test_event_fd3_finished(struct tevent_context *ev_ctx,
1217 struct tevent_timer *te,
1218 struct timeval tval,
1219 void *private_data)
1221 struct test_event_fd3_state *state =
1222 (struct test_event_fd3_state *)private_data;
1224 if (!test_event_fd3_assert_timeout(state, 5, __func__)) {
1225 return;
1229 * this should never be triggered
1231 if (state->sock0.fde_callback != NULL) {
1232 state->finished = true;
1233 state->error = __location__;
1234 return;
1236 if (state->sock1.fde_callback != NULL) {
1237 state->finished = true;
1238 state->error = __location__;
1239 return;
1242 state->finished = true;
1245 static bool test_event_fd3(struct torture_context *tctx,
1246 const void *test_data)
1248 struct test_event_fd3_state state = {
1249 .tctx = tctx,
1250 .backend = (const char *)test_data,
1252 int rc;
1253 int sock[2];
1255 state.ev = test_tevent_context_init_byname(tctx, state.backend);
1256 if (state.ev == NULL) {
1257 torture_skip(tctx, talloc_asprintf(tctx,
1258 "event backend '%s' not supported\n",
1259 state.backend));
1260 return true;
1263 torture_comment(tctx, "backend '%s' - %s\n",
1264 state.backend, __FUNCTION__);
1266 sock[0] = -1;
1267 sock[1] = -1;
1268 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
1269 torture_assert_int_equal(tctx, rc, 0, "socketpair()");
1271 state.start_time = timeval_current();
1272 state.te1 = tevent_add_timer(state.ev, state.ev,
1273 timeval_add(&state.start_time, 5, 0),
1274 test_event_fd3_finished, &state);
1275 torture_assert(tctx, state.te1 != NULL, "tevent_add_timer()");
1276 state.te2 = tevent_add_timer(state.ev, state.ev,
1277 timeval_add(&state.start_time, 1, 0),
1278 test_event_fd3_writeable, &state);
1279 torture_assert(tctx, state.te2 != NULL, "tevent_add_timer()");
1280 state.te3 = tevent_add_timer(state.ev, state.ev,
1281 timeval_add(&state.start_time, 2, 0),
1282 test_event_fd3_readable, &state);
1283 torture_assert(tctx, state.te3 != NULL, "tevent_add_timer()");
1284 state.te4 = tevent_add_timer(state.ev, state.ev,
1285 timeval_add(&state.start_time, 3, 0),
1286 test_event_fd3_not_writeable, &state);
1287 torture_assert(tctx, state.te4 != NULL, "tevent_add_timer()");
1288 state.te5 = tevent_add_timer(state.ev, state.ev,
1289 timeval_add(&state.start_time, 4, 0),
1290 test_event_fd3_off, &state);
1291 torture_assert(tctx, state.te5 != NULL, "tevent_add_timer()");
1293 state.sock0.state = &state;
1294 state.sock0.sock_name = "sock0";
1295 state.sock0.fd = sock[0];
1296 state.sock0.fde1.sock = &state.sock0;
1297 state.sock0.fde1.fde = tevent_add_fd(state.ev, state.ev,
1298 state.sock0.fd,
1300 test_event_fd3_sock_handler,
1301 &state.sock0.fde1);
1302 torture_assert(tctx, state.sock0.fde1.fde != NULL, "tevent_add_fd()");
1303 tevent_fd_set_auto_close(state.sock0.fde1.fde);
1304 state.sock0.fde2.sock = &state.sock0;
1305 state.sock0.fde2.fde = tevent_add_fd(state.ev, state.ev,
1306 state.sock0.fd,
1308 test_event_fd3_sock_handler,
1309 &state.sock0.fde2);
1310 torture_assert(tctx, state.sock0.fde2.fde != NULL, "tevent_add_fd()");
1311 state.sock0.fde3.sock = &state.sock0;
1312 state.sock0.fde3.fde = tevent_add_fd(state.ev, state.ev,
1313 state.sock0.fd,
1315 test_event_fd3_sock_handler,
1316 &state.sock0.fde3);
1317 torture_assert(tctx, state.sock0.fde3.fde != NULL, "tevent_add_fd()");
1318 state.sock0.fde4.sock = &state.sock0;
1319 state.sock0.fde4.fde = tevent_add_fd(state.ev, state.ev,
1320 state.sock0.fd,
1322 test_event_fd3_sock_handler,
1323 &state.sock0.fde4);
1324 torture_assert(tctx, state.sock0.fde4.fde != NULL, "tevent_add_fd()");
1325 state.sock0.fde5.sock = &state.sock0;
1326 state.sock0.fde5.fde = tevent_add_fd(state.ev, state.ev,
1327 state.sock0.fd,
1329 test_event_fd3_sock_handler,
1330 &state.sock0.fde5);
1331 torture_assert(tctx, state.sock0.fde5.fde != NULL, "tevent_add_fd()");
1332 state.sock0.fde6.sock = &state.sock0;
1333 state.sock0.fde6.fde = tevent_add_fd(state.ev, state.ev,
1334 state.sock0.fd,
1336 test_event_fd3_sock_handler,
1337 &state.sock0.fde6);
1338 torture_assert(tctx, state.sock0.fde6.fde != NULL, "tevent_add_fd()");
1339 state.sock0.fde7.sock = &state.sock0;
1340 state.sock0.fde7.fde = tevent_add_fd(state.ev, state.ev,
1341 state.sock0.fd,
1343 test_event_fd3_sock_handler,
1344 &state.sock0.fde7);
1345 torture_assert(tctx, state.sock0.fde7.fde != NULL, "tevent_add_fd()");
1346 state.sock0.fde8.sock = &state.sock0;
1347 state.sock0.fde8.fde = tevent_add_fd(state.ev, state.ev,
1348 state.sock0.fd,
1350 test_event_fd3_sock_handler,
1351 &state.sock0.fde8);
1352 torture_assert(tctx, state.sock0.fde8.fde != NULL, "tevent_add_fd()");
1353 state.sock0.fde9.sock = &state.sock0;
1354 state.sock0.fde9.fde = tevent_add_fd(state.ev, state.ev,
1355 state.sock0.fd,
1357 test_event_fd3_sock_handler,
1358 &state.sock0.fde9);
1359 torture_assert(tctx, state.sock0.fde9.fde != NULL, "tevent_add_fd()");
1361 state.sock1.state = &state;
1362 state.sock1.sock_name = "sock1";
1363 state.sock1.fd = sock[1];
1364 state.sock1.fde1.sock = &state.sock1;
1365 state.sock1.fde1.fde = tevent_add_fd(state.ev, state.ev,
1366 state.sock1.fd,
1368 test_event_fd3_sock_handler,
1369 &state.sock1.fde1);
1370 torture_assert(tctx, state.sock1.fde1.fde != NULL, "tevent_add_fd()");
1371 tevent_fd_set_auto_close(state.sock1.fde1.fde);
1372 state.sock1.fde2.sock = &state.sock1;
1373 state.sock1.fde2.fde = tevent_add_fd(state.ev, state.ev,
1374 state.sock1.fd,
1376 test_event_fd3_sock_handler,
1377 &state.sock1.fde2);
1378 torture_assert(tctx, state.sock1.fde2.fde != NULL, "tevent_add_fd()");
1379 state.sock1.fde3.sock = &state.sock1;
1380 state.sock1.fde3.fde = tevent_add_fd(state.ev, state.ev,
1381 state.sock1.fd,
1383 test_event_fd3_sock_handler,
1384 &state.sock1.fde3);
1385 torture_assert(tctx, state.sock1.fde3.fde != NULL, "tevent_add_fd()");
1386 state.sock1.fde4.sock = &state.sock1;
1387 state.sock1.fde4.fde = tevent_add_fd(state.ev, state.ev,
1388 state.sock1.fd,
1390 test_event_fd3_sock_handler,
1391 &state.sock1.fde4);
1392 torture_assert(tctx, state.sock1.fde4.fde != NULL, "tevent_add_fd()");
1393 state.sock1.fde5.sock = &state.sock1;
1394 state.sock1.fde5.fde = tevent_add_fd(state.ev, state.ev,
1395 state.sock1.fd,
1397 test_event_fd3_sock_handler,
1398 &state.sock1.fde5);
1399 torture_assert(tctx, state.sock1.fde5.fde != NULL, "tevent_add_fd()");
1400 state.sock1.fde6.sock = &state.sock1;
1401 state.sock1.fde6.fde = tevent_add_fd(state.ev, state.ev,
1402 state.sock1.fd,
1404 test_event_fd3_sock_handler,
1405 &state.sock1.fde6);
1406 torture_assert(tctx, state.sock1.fde6.fde != NULL, "tevent_add_fd()");
1407 state.sock1.fde7.sock = &state.sock1;
1408 state.sock1.fde7.fde = tevent_add_fd(state.ev, state.ev,
1409 state.sock1.fd,
1411 test_event_fd3_sock_handler,
1412 &state.sock1.fde7);
1413 torture_assert(tctx, state.sock1.fde7.fde != NULL, "tevent_add_fd()");
1414 state.sock1.fde8.sock = &state.sock1;
1415 state.sock1.fde8.fde = tevent_add_fd(state.ev, state.ev,
1416 state.sock1.fd,
1418 test_event_fd3_sock_handler,
1419 &state.sock1.fde8);
1420 torture_assert(tctx, state.sock1.fde8.fde != NULL, "tevent_add_fd()");
1421 state.sock1.fde9.sock = &state.sock1;
1422 state.sock1.fde9.fde = tevent_add_fd(state.ev, state.ev,
1423 state.sock1.fd,
1425 test_event_fd3_sock_handler,
1426 &state.sock1.fde9);
1427 torture_assert(tctx, state.sock1.fde9.fde != NULL, "tevent_add_fd()");
1429 while (!state.finished) {
1430 errno = 0;
1431 if (tevent_loop_once(state.ev) == -1) {
1432 talloc_free(state.ev);
1433 torture_fail(tctx, talloc_asprintf(tctx,
1434 "Failed event loop %s\n",
1435 strerror(errno)));
1439 talloc_free(state.ev);
1441 torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
1442 "%s", state.error));
1444 return true;
1447 struct test_wrapper_state {
1448 struct torture_context *tctx;
1449 int num_events;
1450 int num_wrap_handlers;
1453 static bool test_wrapper_before_use(struct tevent_context *wrap_ev,
1454 void *private_data,
1455 struct tevent_context *main_ev,
1456 const char *location)
1458 struct test_wrapper_state *state =
1459 talloc_get_type_abort(private_data,
1460 struct test_wrapper_state);
1462 torture_comment(state->tctx, "%s\n", __func__);
1463 state->num_wrap_handlers++;
1464 return true;
1467 static void test_wrapper_after_use(struct tevent_context *wrap_ev,
1468 void *private_data,
1469 struct tevent_context *main_ev,
1470 const char *location)
1472 struct test_wrapper_state *state =
1473 talloc_get_type_abort(private_data,
1474 struct test_wrapper_state);
1476 torture_comment(state->tctx, "%s\n", __func__);
1477 state->num_wrap_handlers++;
1480 static void test_wrapper_before_fd_handler(struct tevent_context *wrap_ev,
1481 void *private_data,
1482 struct tevent_context *main_ev,
1483 struct tevent_fd *fde,
1484 uint16_t flags,
1485 const char *handler_name,
1486 const char *location)
1488 struct test_wrapper_state *state =
1489 talloc_get_type_abort(private_data,
1490 struct test_wrapper_state);
1492 torture_comment(state->tctx, "%s\n", __func__);
1493 state->num_wrap_handlers++;
1496 static void test_wrapper_after_fd_handler(struct tevent_context *wrap_ev,
1497 void *private_data,
1498 struct tevent_context *main_ev,
1499 struct tevent_fd *fde,
1500 uint16_t flags,
1501 const char *handler_name,
1502 const char *location)
1504 struct test_wrapper_state *state =
1505 talloc_get_type_abort(private_data,
1506 struct test_wrapper_state);
1508 torture_comment(state->tctx, "%s\n", __func__);
1509 state->num_wrap_handlers++;
1512 static void test_wrapper_before_timer_handler(struct tevent_context *wrap_ev,
1513 void *private_data,
1514 struct tevent_context *main_ev,
1515 struct tevent_timer *te,
1516 struct timeval requested_time,
1517 struct timeval trigger_time,
1518 const char *handler_name,
1519 const char *location)
1521 struct test_wrapper_state *state =
1522 talloc_get_type_abort(private_data,
1523 struct test_wrapper_state);
1525 torture_comment(state->tctx, "%s\n", __func__);
1526 state->num_wrap_handlers++;
1529 static void test_wrapper_after_timer_handler(struct tevent_context *wrap_ev,
1530 void *private_data,
1531 struct tevent_context *main_ev,
1532 struct tevent_timer *te,
1533 struct timeval requested_time,
1534 struct timeval trigger_time,
1535 const char *handler_name,
1536 const char *location)
1538 struct test_wrapper_state *state =
1539 talloc_get_type_abort(private_data,
1540 struct test_wrapper_state);
1542 torture_comment(state->tctx, "%s\n", __func__);
1543 state->num_wrap_handlers++;
1546 static void test_wrapper_before_immediate_handler(struct tevent_context *wrap_ev,
1547 void *private_data,
1548 struct tevent_context *main_ev,
1549 struct tevent_immediate *im,
1550 const char *handler_name,
1551 const char *location)
1553 struct test_wrapper_state *state =
1554 talloc_get_type_abort(private_data,
1555 struct test_wrapper_state);
1557 torture_comment(state->tctx, "%s\n", __func__);
1558 state->num_wrap_handlers++;
1561 static void test_wrapper_after_immediate_handler(struct tevent_context *wrap_ev,
1562 void *private_data,
1563 struct tevent_context *main_ev,
1564 struct tevent_immediate *im,
1565 const char *handler_name,
1566 const char *location)
1568 struct test_wrapper_state *state =
1569 talloc_get_type_abort(private_data,
1570 struct test_wrapper_state);
1572 torture_comment(state->tctx, "%s\n", __func__);
1573 state->num_wrap_handlers++;
1576 static void test_wrapper_before_signal_handler(struct tevent_context *wrap_ev,
1577 void *private_data,
1578 struct tevent_context *main_ev,
1579 struct tevent_signal *se,
1580 int signum,
1581 int count,
1582 void *siginfo,
1583 const char *handler_name,
1584 const char *location)
1586 struct test_wrapper_state *state =
1587 talloc_get_type_abort(private_data,
1588 struct test_wrapper_state);
1590 torture_comment(state->tctx, "%s\n", __func__);
1591 state->num_wrap_handlers++;
1594 static void test_wrapper_after_signal_handler(struct tevent_context *wrap_ev,
1595 void *private_data,
1596 struct tevent_context *main_ev,
1597 struct tevent_signal *se,
1598 int signum,
1599 int count,
1600 void *siginfo,
1601 const char *handler_name,
1602 const char *location)
1604 struct test_wrapper_state *state =
1605 talloc_get_type_abort(private_data,
1606 struct test_wrapper_state);
1608 torture_comment(state->tctx, "%s\n", __func__);
1609 state->num_wrap_handlers++;
1612 static const struct tevent_wrapper_ops test_wrapper_ops = {
1613 .name = "test_wrapper",
1614 .before_use = test_wrapper_before_use,
1615 .after_use = test_wrapper_after_use,
1616 .before_fd_handler = test_wrapper_before_fd_handler,
1617 .after_fd_handler = test_wrapper_after_fd_handler,
1618 .before_timer_handler = test_wrapper_before_timer_handler,
1619 .after_timer_handler = test_wrapper_after_timer_handler,
1620 .before_immediate_handler = test_wrapper_before_immediate_handler,
1621 .after_immediate_handler = test_wrapper_after_immediate_handler,
1622 .before_signal_handler = test_wrapper_before_signal_handler,
1623 .after_signal_handler = test_wrapper_after_signal_handler,
1626 static void test_wrapper_timer_handler(struct tevent_context *ev,
1627 struct tevent_timer *te,
1628 struct timeval tv,
1629 void *private_data)
1631 struct test_wrapper_state *state =
1632 (struct test_wrapper_state *)private_data;
1635 torture_comment(state->tctx, "timer handler\n");
1637 state->num_events++;
1638 talloc_free(te);
1639 return;
1642 static void test_wrapper_fd_handler(struct tevent_context *ev,
1643 struct tevent_fd *fde,
1644 unsigned short fd_flags,
1645 void *private_data)
1647 struct test_wrapper_state *state =
1648 (struct test_wrapper_state *)private_data;
1650 torture_comment(state->tctx, "fd handler\n");
1652 state->num_events++;
1653 talloc_free(fde);
1654 return;
1657 static void test_wrapper_immediate_handler(struct tevent_context *ev,
1658 struct tevent_immediate *im,
1659 void *private_data)
1661 struct test_wrapper_state *state =
1662 (struct test_wrapper_state *)private_data;
1664 state->num_events++;
1665 talloc_free(im);
1667 torture_comment(state->tctx, "immediate handler\n");
1668 return;
1671 static void test_wrapper_signal_handler(struct tevent_context *ev,
1672 struct tevent_signal *se,
1673 int signum,
1674 int count,
1675 void *siginfo,
1676 void *private_data)
1678 struct test_wrapper_state *state =
1679 (struct test_wrapper_state *)private_data;
1681 torture_comment(state->tctx, "signal handler\n");
1683 state->num_events++;
1684 talloc_free(se);
1685 return;
1688 static bool test_wrapper(struct torture_context *tctx,
1689 const void *test_data)
1691 struct test_wrapper_state *state = NULL;
1692 int sock[2] = { -1, -1};
1693 uint8_t c = 0;
1694 const int num_events = 4;
1695 const char *backend = (const char *)test_data;
1696 struct tevent_context *ev = NULL;
1697 struct tevent_context *wrap_ev = NULL;
1698 struct tevent_fd *fde = NULL;
1699 struct tevent_timer *te = NULL;
1700 struct tevent_signal *se = NULL;
1701 struct tevent_immediate *im = NULL;
1702 int ret;
1703 bool ok = false;
1704 bool ret2;
1706 ev = test_tevent_context_init_byname(tctx, backend);
1707 if (ev == NULL) {
1708 torture_skip(tctx, talloc_asprintf(tctx,
1709 "event backend '%s' not supported\n",
1710 backend));
1711 return true;
1714 torture_comment(tctx, "tevent backend '%s'\n", backend);
1716 wrap_ev = tevent_context_wrapper_create(
1717 ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state);
1718 torture_assert_not_null_goto(tctx, wrap_ev, ok, done,
1719 "tevent_context_wrapper_create failed\n");
1720 *state = (struct test_wrapper_state) {
1721 .tctx = tctx,
1724 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
1725 torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n");
1727 te = tevent_add_timer(wrap_ev, wrap_ev,
1728 timeval_current_ofs(0, 0),
1729 test_wrapper_timer_handler, state);
1730 torture_assert_not_null_goto(tctx, te, ok, done,
1731 "tevent_add_timer failed\n");
1733 fde = tevent_add_fd(wrap_ev, wrap_ev,
1734 sock[1],
1735 TEVENT_FD_READ,
1736 test_wrapper_fd_handler,
1737 state);
1738 torture_assert_not_null_goto(tctx, fde, ok, done,
1739 "tevent_add_fd failed\n");
1741 im = tevent_create_immediate(wrap_ev);
1742 torture_assert_not_null_goto(tctx, im, ok, done,
1743 "tevent_create_immediate failed\n");
1745 se = tevent_add_signal(wrap_ev, wrap_ev,
1746 SIGUSR1,
1748 test_wrapper_signal_handler,
1749 state);
1750 torture_assert_not_null_goto(tctx, se, ok, done,
1751 "tevent_add_signal failed\n");
1753 do_write(sock[0], &c, 1);
1754 kill(getpid(), SIGUSR1);
1755 tevent_schedule_immediate(im,
1756 wrap_ev,
1757 test_wrapper_immediate_handler,
1758 state);
1760 ret2 = tevent_context_push_use(wrap_ev);
1761 torture_assert_goto(tctx, ret2, ok, done, "tevent_context_push_use(wrap_ev) failed\n");
1762 ret2 = tevent_context_push_use(ev);
1763 torture_assert_goto(tctx, ret2, ok, pop_use, "tevent_context_push_use(ev) failed\n");
1764 tevent_context_pop_use(ev);
1765 tevent_context_pop_use(wrap_ev);
1767 ret = tevent_loop_wait(ev);
1768 torture_assert_int_equal_goto(tctx, ret, 0, ok, done, "tevent_loop_wait failed\n");
1770 torture_comment(tctx, "Num events: %d\n", state->num_events);
1771 torture_comment(tctx, "Num wrap handlers: %d\n",
1772 state->num_wrap_handlers);
1774 torture_assert_int_equal_goto(tctx, state->num_events, num_events, ok, done,
1775 "Wrong event count\n");
1776 torture_assert_int_equal_goto(tctx, state->num_wrap_handlers,
1777 num_events*2+2,
1778 ok, done, "Wrong wrapper count\n");
1780 ok = true;
1782 done:
1783 TALLOC_FREE(wrap_ev);
1784 TALLOC_FREE(ev);
1786 if (sock[0] != -1) {
1787 close(sock[0]);
1789 if (sock[1] != -1) {
1790 close(sock[1]);
1792 return ok;
1793 pop_use:
1794 tevent_context_pop_use(wrap_ev);
1795 goto done;
1798 static void test_free_wrapper_signal_handler(struct tevent_context *ev,
1799 struct tevent_signal *se,
1800 int signum,
1801 int count,
1802 void *siginfo,
1803 void *private_data)
1805 struct torture_context *tctx =
1806 talloc_get_type_abort(private_data,
1807 struct torture_context);
1809 torture_comment(tctx, "signal handler\n");
1811 talloc_free(se);
1814 * signal handlers have highest priority in tevent, so this signal
1815 * handler will always be started before the other handlers
1816 * below. Freeing the (wrapper) event context here tests that the
1817 * wrapper implementation correctly handles the wrapper ev going away
1818 * with pending events.
1820 talloc_free(ev);
1821 return;
1824 static void test_free_wrapper_fd_handler(struct tevent_context *ev,
1825 struct tevent_fd *fde,
1826 unsigned short fd_flags,
1827 void *private_data)
1830 * This should never be called as
1831 * test_free_wrapper_signal_handler()
1832 * already destroyed the wrapper tevent_context.
1834 abort();
1837 static void test_free_wrapper_immediate_handler(struct tevent_context *ev,
1838 struct tevent_immediate *im,
1839 void *private_data)
1842 * This should never be called as
1843 * test_free_wrapper_signal_handler()
1844 * already destroyed the wrapper tevent_context.
1846 abort();
1849 static void test_free_wrapper_timer_handler(struct tevent_context *ev,
1850 struct tevent_timer *te,
1851 struct timeval tv,
1852 void *private_data)
1855 * This should never be called as
1856 * test_free_wrapper_signal_handler()
1857 * already destroyed the wrapper tevent_context.
1859 abort();
1862 static bool test_free_wrapper(struct torture_context *tctx,
1863 const void *test_data)
1865 struct test_wrapper_state *state = NULL;
1866 int sock[2] = { -1, -1};
1867 uint8_t c = 0;
1868 const char *backend = (const char *)test_data;
1869 TALLOC_CTX *frame = talloc_stackframe();
1870 struct tevent_context *ev = NULL;
1871 struct tevent_context *wrap_ev = NULL;
1872 struct tevent_fd *fde = NULL;
1873 struct tevent_timer *te = NULL;
1874 struct tevent_signal *se = NULL;
1875 struct tevent_immediate *im = NULL;
1876 int ret;
1877 bool ok = false;
1879 ev = test_tevent_context_init_byname(frame, backend);
1880 if (ev == NULL) {
1881 torture_skip(tctx, talloc_asprintf(tctx,
1882 "event backend '%s' not supported\n",
1883 backend));
1884 return true;
1887 torture_comment(tctx, "tevent backend '%s'\n", backend);
1889 wrap_ev = tevent_context_wrapper_create(
1890 ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state);
1891 torture_assert_not_null_goto(tctx, wrap_ev, ok, done,
1892 "tevent_context_wrapper_create failed\n");
1893 *state = (struct test_wrapper_state) {
1894 .tctx = tctx,
1897 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
1898 torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n");
1900 fde = tevent_add_fd(wrap_ev, frame,
1901 sock[1],
1902 TEVENT_FD_READ,
1903 test_free_wrapper_fd_handler,
1904 NULL);
1905 torture_assert_not_null_goto(tctx, fde, ok, done,
1906 "tevent_add_fd failed\n");
1908 te = tevent_add_timer(wrap_ev, frame,
1909 timeval_current_ofs(0, 0),
1910 test_free_wrapper_timer_handler, NULL);
1911 torture_assert_not_null_goto(tctx, te, ok, done,
1912 "tevent_add_timer failed\n");
1914 im = tevent_create_immediate(frame);
1915 torture_assert_not_null_goto(tctx, im, ok, done,
1916 "tevent_create_immediate failed\n");
1918 se = tevent_add_signal(wrap_ev, frame,
1919 SIGUSR1,
1921 test_free_wrapper_signal_handler,
1922 tctx);
1923 torture_assert_not_null_goto(tctx, se, ok, done,
1924 "tevent_add_signal failed\n");
1926 do_write(sock[0], &c, 1);
1927 kill(getpid(), SIGUSR1);
1928 tevent_schedule_immediate(im,
1929 wrap_ev,
1930 test_free_wrapper_immediate_handler,
1931 NULL);
1933 ret = tevent_loop_wait(ev);
1934 torture_assert_goto(tctx, ret == 0, ok, done, "tevent_loop_wait failed\n");
1936 ok = true;
1938 done:
1939 TALLOC_FREE(frame);
1941 if (sock[0] != -1) {
1942 close(sock[0]);
1944 if (sock[1] != -1) {
1945 close(sock[1]);
1947 return ok;
1950 #ifdef HAVE_PTHREAD
1952 static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
1953 static bool do_shutdown = false;
1955 static void test_event_threaded_lock(void)
1957 int ret;
1958 ret = pthread_mutex_lock(&threaded_mutex);
1959 assert(ret == 0);
1962 static void test_event_threaded_unlock(void)
1964 int ret;
1965 ret = pthread_mutex_unlock(&threaded_mutex);
1966 assert(ret == 0);
1969 static void test_event_threaded_trace(enum tevent_trace_point point,
1970 void *private_data)
1972 switch (point) {
1973 case TEVENT_TRACE_BEFORE_WAIT:
1974 test_event_threaded_unlock();
1975 break;
1976 case TEVENT_TRACE_AFTER_WAIT:
1977 test_event_threaded_lock();
1978 break;
1979 case TEVENT_TRACE_BEFORE_LOOP_ONCE:
1980 case TEVENT_TRACE_AFTER_LOOP_ONCE:
1981 break;
1985 static void test_event_threaded_timer(struct tevent_context *ev,
1986 struct tevent_timer *te,
1987 struct timeval current_time,
1988 void *private_data)
1990 return;
1993 static void *test_event_poll_thread(void *private_data)
1995 struct tevent_context *ev = (struct tevent_context *)private_data;
1997 test_event_threaded_lock();
1999 while (true) {
2000 int ret;
2001 ret = tevent_loop_once(ev);
2002 assert(ret == 0);
2003 if (do_shutdown) {
2004 test_event_threaded_unlock();
2005 return NULL;
2011 static void test_event_threaded_read_handler(struct tevent_context *ev,
2012 struct tevent_fd *fde,
2013 uint16_t flags,
2014 void *private_data)
2016 int *pfd = (int *)private_data;
2017 char c;
2018 ssize_t nread;
2020 if ((flags & TEVENT_FD_READ) == 0) {
2021 return;
2024 do {
2025 nread = read(*pfd, &c, 1);
2026 } while ((nread == -1) && (errno == EINTR));
2028 assert(nread == 1);
2031 static bool test_event_context_threaded(struct torture_context *test,
2032 const void *test_data)
2034 struct tevent_context *ev;
2035 struct tevent_timer *te;
2036 struct tevent_fd *fde;
2037 pthread_t poll_thread;
2038 int fds[2];
2039 int ret;
2040 char c = 0;
2042 ev = test_tevent_context_init_byname(test, "poll_mt");
2043 torture_assert(test, ev != NULL, "poll_mt not supported");
2045 tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
2047 te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
2048 test_event_threaded_timer, NULL);
2049 torture_assert(test, te != NULL, "Could not add timer");
2051 ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
2052 torture_assert(test, ret == 0, "Could not create poll thread");
2054 ret = pipe(fds);
2055 torture_assert(test, ret == 0, "Could not create pipe");
2057 poll(NULL, 0, 100);
2059 test_event_threaded_lock();
2061 fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
2062 test_event_threaded_read_handler, &fds[0]);
2063 torture_assert(test, fde != NULL, "Could not add fd event");
2065 test_event_threaded_unlock();
2067 poll(NULL, 0, 100);
2069 do_write(fds[1], &c, 1);
2071 poll(NULL, 0, 100);
2073 test_event_threaded_lock();
2074 do_shutdown = true;
2075 test_event_threaded_unlock();
2077 do_write(fds[1], &c, 1);
2079 ret = pthread_join(poll_thread, NULL);
2080 torture_assert(test, ret == 0, "pthread_join failed");
2082 return true;
2085 #define NUM_TEVENT_THREADS 100
2087 /* Ugly, but needed for torture_comment... */
2088 static struct torture_context *thread_test_ctx;
2089 static pthread_t thread_map[NUM_TEVENT_THREADS];
2090 static unsigned thread_counter;
2092 /* Called in master thread context */
2093 static void callback_nowait(struct tevent_context *ev,
2094 struct tevent_immediate *im,
2095 void *private_ptr)
2097 pthread_t *thread_id_ptr =
2098 talloc_get_type_abort(private_ptr, pthread_t);
2099 unsigned i;
2101 for (i = 0; i < NUM_TEVENT_THREADS; i++) {
2102 if (pthread_equal(*thread_id_ptr,
2103 thread_map[i])) {
2104 break;
2107 torture_comment(thread_test_ctx,
2108 "Callback %u from thread %u\n",
2109 thread_counter,
2111 thread_counter++;
2114 /* Blast the master tevent_context with a callback, no waiting. */
2115 static void *thread_fn_nowait(void *private_ptr)
2117 struct tevent_thread_proxy *master_tp =
2118 talloc_get_type_abort(private_ptr, struct tevent_thread_proxy);
2119 struct tevent_immediate *im;
2120 pthread_t *thread_id_ptr;
2122 im = tevent_create_immediate(NULL);
2123 if (im == NULL) {
2124 return NULL;
2126 thread_id_ptr = talloc(NULL, pthread_t);
2127 if (thread_id_ptr == NULL) {
2128 return NULL;
2130 *thread_id_ptr = pthread_self();
2132 tevent_thread_proxy_schedule(master_tp,
2133 &im,
2134 callback_nowait,
2135 &thread_id_ptr);
2136 return NULL;
2139 static void timeout_fn(struct tevent_context *ev,
2140 struct tevent_timer *te,
2141 struct timeval tv, void *p)
2143 thread_counter = NUM_TEVENT_THREADS * 10;
2146 static bool test_multi_tevent_threaded(struct torture_context *test,
2147 const void *test_data)
2149 unsigned i;
2150 struct tevent_context *master_ev;
2151 struct tevent_thread_proxy *tp;
2153 talloc_disable_null_tracking();
2155 /* Ugly global stuff. */
2156 thread_test_ctx = test;
2157 thread_counter = 0;
2159 master_ev = test_tevent_context_init(NULL);
2160 if (master_ev == NULL) {
2161 return false;
2164 tp = tevent_thread_proxy_create(master_ev);
2165 if (tp == NULL) {
2166 torture_fail(test,
2167 talloc_asprintf(test,
2168 "tevent_thread_proxy_create failed\n"));
2169 talloc_free(master_ev);
2170 return false;
2173 for (i = 0; i < NUM_TEVENT_THREADS; i++) {
2174 int ret = pthread_create(&thread_map[i],
2175 NULL,
2176 thread_fn_nowait,
2177 tp);
2178 if (ret != 0) {
2179 torture_fail(test,
2180 talloc_asprintf(test,
2181 "Failed to create thread %i, %d\n",
2182 i, ret));
2183 return false;
2187 /* Ensure we don't wait more than 10 seconds. */
2188 tevent_add_timer(master_ev,
2189 master_ev,
2190 timeval_current_ofs(10,0),
2191 timeout_fn,
2192 NULL);
2194 while (thread_counter < NUM_TEVENT_THREADS) {
2195 int ret = tevent_loop_once(master_ev);
2196 torture_assert(test, ret == 0, "tevent_loop_once failed");
2199 torture_assert(test, thread_counter == NUM_TEVENT_THREADS,
2200 "thread_counter fail\n");
2202 talloc_free(master_ev);
2203 return true;
2206 struct reply_state {
2207 struct tevent_thread_proxy *reply_tp;
2208 pthread_t thread_id;
2209 int *p_finished;
2212 static void thread_timeout_fn(struct tevent_context *ev,
2213 struct tevent_timer *te,
2214 struct timeval tv, void *p)
2216 int *p_finished = (int *)p;
2218 *p_finished = 2;
2221 /* Called in child-thread context */
2222 static void thread_callback(struct tevent_context *ev,
2223 struct tevent_immediate *im,
2224 void *private_ptr)
2226 struct reply_state *rsp =
2227 talloc_get_type_abort(private_ptr, struct reply_state);
2229 talloc_steal(ev, rsp);
2230 *rsp->p_finished = 1;
2233 /* Called in master thread context */
2234 static void master_callback(struct tevent_context *ev,
2235 struct tevent_immediate *im,
2236 void *private_ptr)
2238 struct reply_state *rsp =
2239 talloc_get_type_abort(private_ptr, struct reply_state);
2240 unsigned i;
2242 talloc_steal(ev, rsp);
2244 for (i = 0; i < NUM_TEVENT_THREADS; i++) {
2245 if (pthread_equal(rsp->thread_id,
2246 thread_map[i])) {
2247 break;
2250 torture_comment(thread_test_ctx,
2251 "Callback %u from thread %u\n",
2252 thread_counter,
2254 /* Now reply to the thread ! */
2255 tevent_thread_proxy_schedule(rsp->reply_tp,
2256 &im,
2257 thread_callback,
2258 &rsp);
2260 thread_counter++;
2263 static void *thread_fn_1(void *private_ptr)
2265 struct tevent_thread_proxy *master_tp =
2266 talloc_get_type_abort(private_ptr, struct tevent_thread_proxy);
2267 struct tevent_thread_proxy *tp;
2268 struct tevent_immediate *im;
2269 struct tevent_context *ev;
2270 struct reply_state *rsp;
2271 int finished = 0;
2272 int ret;
2274 ev = tevent_context_init(NULL);
2275 if (ev == NULL) {
2276 return NULL;
2279 tp = tevent_thread_proxy_create(ev);
2280 if (tp == NULL) {
2281 talloc_free(ev);
2282 return NULL;
2285 im = tevent_create_immediate(ev);
2286 if (im == NULL) {
2287 talloc_free(ev);
2288 return NULL;
2291 rsp = talloc(ev, struct reply_state);
2292 if (rsp == NULL) {
2293 talloc_free(ev);
2294 return NULL;
2297 rsp->thread_id = pthread_self();
2298 rsp->reply_tp = tp;
2299 rsp->p_finished = &finished;
2301 /* Introduce a little randomness into the mix.. */
2302 usleep(random() % 7000);
2304 tevent_thread_proxy_schedule(master_tp,
2305 &im,
2306 master_callback,
2307 &rsp);
2309 /* Ensure we don't wait more than 10 seconds. */
2310 tevent_add_timer(ev,
2312 timeval_current_ofs(10,0),
2313 thread_timeout_fn,
2314 &finished);
2316 while (finished == 0) {
2317 ret = tevent_loop_once(ev);
2318 assert(ret == 0);
2321 if (finished > 1) {
2322 /* Timeout ! */
2323 abort();
2327 * NB. We should talloc_free(ev) here, but if we do
2328 * we currently get hit by helgrind Fix #323432
2329 * "When calling pthread_cond_destroy or pthread_mutex_destroy
2330 * with initializers as argument Helgrind (incorrectly) reports errors."
2332 * http://valgrind.10908.n7.nabble.com/Helgrind-3-9-0-false-positive-
2333 * with-pthread-mutex-destroy-td47757.html
2335 * Helgrind doesn't understand that the request/reply
2336 * messages provide synchronization between the lock/unlock
2337 * in tevent_thread_proxy_schedule(), and the pthread_destroy()
2338 * when the struct tevent_thread_proxy object is talloc_free'd.
2340 * As a work-around for now return ev for the parent thread to free.
2342 return ev;
2345 static bool test_multi_tevent_threaded_1(struct torture_context *test,
2346 const void *test_data)
2348 unsigned i;
2349 struct tevent_context *master_ev;
2350 struct tevent_thread_proxy *master_tp;
2351 int ret;
2353 talloc_disable_null_tracking();
2355 /* Ugly global stuff. */
2356 thread_test_ctx = test;
2357 thread_counter = 0;
2359 master_ev = test_tevent_context_init(NULL);
2360 if (master_ev == NULL) {
2361 return false;
2364 master_tp = tevent_thread_proxy_create(master_ev);
2365 if (master_tp == NULL) {
2366 torture_fail(test,
2367 talloc_asprintf(test,
2368 "tevent_thread_proxy_create failed\n"));
2369 talloc_free(master_ev);
2370 return false;
2373 for (i = 0; i < NUM_TEVENT_THREADS; i++) {
2374 ret = pthread_create(&thread_map[i],
2375 NULL,
2376 thread_fn_1,
2377 master_tp);
2378 if (ret != 0) {
2379 torture_fail(test,
2380 talloc_asprintf(test,
2381 "Failed to create thread %i, %d\n",
2382 i, ret));
2383 return false;
2387 while (thread_counter < NUM_TEVENT_THREADS) {
2388 ret = tevent_loop_once(master_ev);
2389 torture_assert(test, ret == 0, "tevent_loop_once failed");
2392 /* Wait for all the threads to finish - join 'em. */
2393 for (i = 0; i < NUM_TEVENT_THREADS; i++) {
2394 void *retval;
2395 ret = pthread_join(thread_map[i], &retval);
2396 torture_assert(test, ret == 0, "pthread_join failed");
2397 /* Free the child thread event context. */
2398 talloc_free(retval);
2401 talloc_free(master_ev);
2402 return true;
2405 struct threaded_test_2 {
2406 struct tevent_threaded_context *tctx;
2407 struct tevent_immediate *im;
2408 pthread_t thread_id;
2411 static void master_callback_2(struct tevent_context *ev,
2412 struct tevent_immediate *im,
2413 void *private_data);
2415 static void *thread_fn_2(void *private_data)
2417 struct threaded_test_2 *state = private_data;
2419 state->thread_id = pthread_self();
2421 usleep(random() % 7000);
2423 tevent_threaded_schedule_immediate(
2424 state->tctx, state->im, master_callback_2, state);
2426 return NULL;
2429 static void master_callback_2(struct tevent_context *ev,
2430 struct tevent_immediate *im,
2431 void *private_data)
2433 struct threaded_test_2 *state = private_data;
2434 int i;
2436 for (i = 0; i < NUM_TEVENT_THREADS; i++) {
2437 if (pthread_equal(state->thread_id, thread_map[i])) {
2438 break;
2441 torture_comment(thread_test_ctx,
2442 "Callback_2 %u from thread %u\n",
2443 thread_counter,
2445 thread_counter++;
2448 static bool test_multi_tevent_threaded_2(struct torture_context *test,
2449 const void *test_data)
2451 unsigned i;
2453 struct tevent_context *ev;
2454 struct tevent_threaded_context *tctx;
2455 int ret;
2457 thread_test_ctx = test;
2458 thread_counter = 0;
2460 ev = test_tevent_context_init(test);
2461 torture_assert(test, ev != NULL, "tevent_context_init failed");
2464 * tevent_re_initialise used to have a bug where it did not
2465 * re-initialise the thread support after taking it
2466 * down. Exercise that code path.
2468 ret = tevent_re_initialise(ev);
2469 torture_assert(test, ret == 0, "tevent_re_initialise failed");
2471 tctx = tevent_threaded_context_create(ev, ev);
2472 torture_assert(test, tctx != NULL,
2473 "tevent_threaded_context_create failed");
2475 for (i=0; i<NUM_TEVENT_THREADS; i++) {
2476 struct threaded_test_2 *state;
2478 state = talloc(ev, struct threaded_test_2);
2479 torture_assert(test, state != NULL, "talloc failed");
2481 state->tctx = tctx;
2482 state->im = tevent_create_immediate(state);
2483 torture_assert(test, state->im != NULL,
2484 "tevent_create_immediate failed");
2486 ret = pthread_create(&thread_map[i], NULL, thread_fn_2, state);
2487 torture_assert(test, ret == 0, "pthread_create failed");
2490 while (thread_counter < NUM_TEVENT_THREADS) {
2491 ret = tevent_loop_once(ev);
2492 torture_assert(test, ret == 0, "tevent_loop_once failed");
2495 /* Wait for all the threads to finish - join 'em. */
2496 for (i = 0; i < NUM_TEVENT_THREADS; i++) {
2497 void *retval;
2498 ret = pthread_join(thread_map[i], &retval);
2499 torture_assert(test, ret == 0, "pthread_join failed");
2500 /* Free the child thread event context. */
2503 talloc_free(tctx);
2504 talloc_free(ev);
2505 return true;
2508 struct test_cached_pid_thread_state {
2509 pid_t thread_cached_pid;
2510 pid_t thread_pid;
2513 static void *test_cached_pid_thread(void *private_data)
2515 struct test_cached_pid_thread_state *state =
2516 (struct test_cached_pid_thread_state *)private_data;
2518 state->thread_cached_pid = tevent_cached_getpid();
2519 state->thread_pid = getpid();
2521 return NULL;
2523 #endif
2525 static bool test_cached_pid(struct torture_context *test,
2526 const void *test_data)
2528 pid_t parent_pid = getpid();
2529 pid_t child_pid;
2530 pid_t finished_pid;
2531 int child_status;
2533 torture_assert(test, tevent_cached_getpid() == parent_pid, "tevent_cached_getpid()");
2535 #ifdef HAVE_PTHREAD
2537 struct test_cached_pid_thread_state state = { .thread_cached_pid = -1, };
2538 pthread_t thread;
2539 void *retval = NULL;
2540 int ret;
2542 ret = pthread_create(&thread, NULL, test_cached_pid_thread, &state);
2543 torture_assert(test, ret == 0, "pthread_create failed");
2545 ret = pthread_join(thread, &retval);
2546 torture_assert(test, ret == 0, "pthread_join failed");
2548 torture_assert(test, state.thread_pid == parent_pid, "getpid() in thread");
2549 torture_assert(test, state.thread_cached_pid == parent_pid, "tevent_cached_getpid() in thread");
2551 #endif /* HAVE_PTHREAD */
2553 child_pid = fork();
2554 if (child_pid == 0) {
2555 /* child */
2556 pid_t pid = getpid();
2557 pid_t cached_pid = tevent_cached_getpid();
2559 if (parent_pid == pid) {
2560 exit(1);
2562 if (pid != cached_pid) {
2563 exit(2);
2565 exit(0);
2567 torture_assert(test, child_pid > 0, "fork failed");
2569 finished_pid = waitpid(child_pid, &child_status, 0);
2570 torture_assert(test, finished_pid == child_pid, "wrong child");
2571 torture_assert(test, child_status == 0, "child_status");
2573 return true;
2576 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
2578 struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
2579 const char **list = tevent_backend_list(suite);
2580 int i;
2582 for (i=0;list && list[i];i++) {
2583 struct torture_suite *backend_suite;
2585 backend_suite = torture_suite_create(mem_ctx, list[i]);
2587 torture_suite_add_simple_tcase_const(backend_suite,
2588 "context",
2589 test_event_context,
2590 (const void *)list[i]);
2591 torture_suite_add_simple_tcase_const(backend_suite,
2592 "fd_speed1",
2593 test_fd_speed1,
2594 (const void *)list[i]);
2595 torture_suite_add_simple_tcase_const(backend_suite,
2596 "fd_speed2",
2597 test_fd_speed2,
2598 (const void *)list[i]);
2599 torture_suite_add_simple_tcase_const(backend_suite,
2600 "fd_speed3",
2601 test_fd_speed3,
2602 (const void *)list[i]);
2603 torture_suite_add_simple_tcase_const(backend_suite,
2604 "fd1",
2605 test_event_fd1,
2606 (const void *)list[i]);
2607 torture_suite_add_simple_tcase_const(backend_suite,
2608 "fd2",
2609 test_event_fd2,
2610 (const void *)list[i]);
2611 torture_suite_add_simple_tcase_const(backend_suite,
2612 "fd3",
2613 test_event_fd3,
2614 (const void *)list[i]);
2615 torture_suite_add_simple_tcase_const(backend_suite,
2616 "wrapper",
2617 test_wrapper,
2618 (const void *)list[i]);
2619 torture_suite_add_simple_tcase_const(backend_suite,
2620 "free_wrapper",
2621 test_free_wrapper,
2622 (const void *)list[i]);
2624 torture_suite_add_suite(suite, backend_suite);
2627 #ifdef HAVE_PTHREAD
2628 torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt",
2629 test_event_context_threaded,
2630 NULL);
2632 torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded",
2633 test_multi_tevent_threaded,
2634 NULL);
2636 torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_1",
2637 test_multi_tevent_threaded_1,
2638 NULL);
2640 torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_2",
2641 test_multi_tevent_threaded_2,
2642 NULL);
2644 #endif
2646 torture_suite_add_simple_tcase_const(suite, "tevent_cached_getpid",
2647 test_cached_pid,
2648 NULL);
2650 return suite;