tevent: add test_event_fd2()
[Samba/gebeck_regimport.git] / lib / tevent / testsuite.c
blob8e3f4af51cc0040a50d23c6bd4102611a4ee4f7e
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 #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"
33 #ifdef HAVE_PTHREAD
34 #include <pthread.h>
35 #include <assert.h>
36 #endif
38 static int fde_count;
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;
44 char c;
45 #ifdef SA_SIGINFO
46 kill(getpid(), SIGUSR1);
47 #endif
48 kill(getpid(), SIGALRM);
50 read(fd[0], &c, 1);
51 fde_count++;
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;
58 char c = 0;
59 write(fd[1], &c, 1);
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");
69 abort();
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");
78 abort();
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;
85 (*finished) = 1;
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;
92 (*countp) += count;
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;
106 #ifdef SA_RESTART
107 struct tevent_signal *se1 = NULL;
108 #endif
109 #ifdef SA_RESETHAND
110 struct tevent_signal *se2 = NULL;
111 #endif
112 #ifdef SA_SIGINFO
113 struct tevent_signal *se3 = NULL;
114 #endif
115 int finished=0;
116 struct timeval t;
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);
121 return true;
124 torture_comment(test, "backend '%s' - %s\n",
125 backend, __FUNCTION__);
127 /* reset globals */
128 fde_count = 0;
130 /* create a pipe */
131 pipe(fd);
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);
149 #ifdef SA_RESTART
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");
152 #endif
153 #ifdef SA_RESETHAND
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");
156 #endif
157 #ifdef SA_SIGINFO
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");
160 #endif
162 t = timeval_current();
163 while (!finished) {
164 errno = 0;
165 if (tevent_loop_once(ev_ctx) == -1) {
166 talloc_free(ev_ctx);
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) {
178 break;
182 torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
184 #ifdef SA_RESTART
185 talloc_free(se1);
186 #endif
188 torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
190 #ifdef SA_RESETHAND
192 * we do not call talloc_free(se2)
193 * because it is already gone,
194 * after triggering the event handler.
196 #endif
198 #ifdef SA_SIGINFO
199 talloc_free(se3);
200 torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
201 #endif
203 talloc_free(ev_ctx);
205 return true;
208 struct test_event_fd1_state {
209 struct torture_context *tctx;
210 const char *backend;
211 struct tevent_context *ev;
212 int sock[2];
213 struct tevent_timer *te;
214 struct tevent_fd *fde0;
215 struct tevent_fd *fde1;
216 bool got_write;
217 bool got_read;
218 bool drain;
219 bool drain_done;
220 unsigned loop_count;
221 bool finished;
222 const char *error;
225 static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx,
226 struct tevent_fd *fde,
227 uint16_t flags,
228 void *private_data)
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__;
236 return;
239 if (state->drain) {
240 ssize_t ret;
241 uint8_t c = 0;
243 if (!(flags & TEVENT_FD_READ)) {
244 state->finished = true;
245 state->error = __location__;
246 return;
249 ret = read(state->sock[0], &c, 1);
250 if (ret == 1) {
251 return;
255 * end of test...
257 tevent_fd_set_flags(fde, 0);
258 state->drain_done = true;
259 return;
262 if (!state->got_write) {
263 uint8_t c = 0;
265 if (flags != TEVENT_FD_WRITE) {
266 state->finished = true;
267 state->error = __location__;
268 return;
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);
278 return;
281 if (!state->got_read) {
282 if (flags != TEVENT_FD_READ) {
283 state->finished = true;
284 state->error = __location__;
285 return;
287 state->got_read = true;
289 TEVENT_FD_NOT_READABLE(fde);
290 return;
293 state->finished = true;
294 state->error = __location__;
295 return;
298 static void test_event_fd1_finished(struct tevent_context *ev_ctx,
299 struct tevent_timer *te,
300 struct timeval tval,
301 void *private_data)
303 struct test_event_fd1_state *state =
304 (struct test_event_fd1_state *)private_data;
306 if (state->drain_done) {
307 state->finished = true;
308 return;
311 if (!state->got_write) {
312 state->finished = true;
313 state->error = __location__;
314 return;
317 if (!state->got_read) {
318 state->finished = true;
319 state->error = __location__;
320 return;
323 state->loop_count++;
324 if (state->loop_count > 3) {
325 state->finished = true;
326 state->error = __location__;
327 return;
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) {
336 state->drain = true;
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;
351 ZERO_STRUCT(state);
352 state.tctx = tctx;
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",
359 state.backend));
360 return true;
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.
374 * We have a loop:
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]
381 * We have a loop:
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
388 state.sock[0] = -1;
389 state.sock[1] = -1;
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,
400 state.sock[1], 0,
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) {
407 errno = 0;
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",
412 strerror(errno)));
416 talloc_free(state.ev);
418 torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
419 "%s", state.error));
421 return true;
424 struct test_event_fd2_state {
425 struct torture_context *tctx;
426 const char *backend;
427 struct tevent_context *ev;
428 struct tevent_timer *te;
429 struct test_event_fd2_sock {
430 struct test_event_fd2_state *state;
431 int fd;
432 struct tevent_fd *fde;
433 size_t num_written;
434 size_t num_read;
435 bool got_full;
436 } sock0, sock1;
437 bool finished;
438 const char *error;
441 static void test_event_fd2_sock_handler(struct tevent_context *ev_ctx,
442 struct tevent_fd *fde,
443 uint16_t flags,
444 void *private_data)
446 struct test_event_fd2_sock *cur_sock =
447 (struct test_event_fd2_sock *)private_data;
448 struct test_event_fd2_state *state = cur_sock->state;
449 struct test_event_fd2_sock *oth_sock = NULL;
450 uint8_t v = 0, c;
451 ssize_t ret;
453 if (cur_sock == &state->sock0) {
454 oth_sock = &state->sock1;
455 } else {
456 oth_sock = &state->sock0;
459 if (oth_sock->num_written == 1) {
460 if (flags != (TEVENT_FD_READ | TEVENT_FD_WRITE)) {
461 state->finished = true;
462 state->error = __location__;
463 return;
467 if (cur_sock->num_read == oth_sock->num_written) {
468 state->finished = true;
469 state->error = __location__;
470 return;
473 if (!(flags & TEVENT_FD_READ)) {
474 state->finished = true;
475 state->error = __location__;
476 return;
479 if (oth_sock->num_read > 0) {
481 * There should be room to write a byte again
483 if (!(flags & TEVENT_FD_WRITE)) {
484 state->finished = true;
485 state->error = __location__;
486 return;
490 if ((flags & TEVENT_FD_WRITE) && !cur_sock->got_full) {
491 v = (uint8_t)cur_sock->num_written;
492 ret = write(cur_sock->fd, &v, 1);
493 if (ret != 1) {
494 state->finished = true;
495 state->error = __location__;
496 return;
498 cur_sock->num_written++;
499 if (cur_sock->num_written > 0x80000000) {
500 state->finished = true;
501 state->error = __location__;
502 return;
504 return;
507 if (!cur_sock->got_full) {
508 cur_sock->got_full = true;
510 if (!oth_sock->got_full) {
512 * cur_sock is full,
513 * lets wait for oth_sock
514 * to be filled
516 tevent_fd_set_flags(cur_sock->fde, 0);
517 return;
521 * oth_sock waited for cur_sock,
522 * lets restart it
524 tevent_fd_set_flags(oth_sock->fde,
525 TEVENT_FD_READ|TEVENT_FD_WRITE);
528 ret = read(cur_sock->fd, &v, 1);
529 if (ret != 1) {
530 state->finished = true;
531 state->error = __location__;
532 return;
534 c = (uint8_t)cur_sock->num_read;
535 if (c != v) {
536 state->finished = true;
537 state->error = __location__;
538 return;
540 cur_sock->num_read++;
542 if (cur_sock->num_read < oth_sock->num_written) {
543 /* there is more to read */
544 return;
547 * we read everything, we need to remove TEVENT_FD_WRITE
548 * to avoid spinning
550 TEVENT_FD_NOT_WRITEABLE(cur_sock->fde);
552 if (oth_sock->num_read == cur_sock->num_written) {
554 * both directions are finished
556 state->finished = true;
559 return;
562 static void test_event_fd2_finished(struct tevent_context *ev_ctx,
563 struct tevent_timer *te,
564 struct timeval tval,
565 void *private_data)
567 struct test_event_fd2_state *state =
568 (struct test_event_fd2_state *)private_data;
571 * this should never be triggered
573 state->finished = true;
574 state->error = __location__;
577 static bool test_event_fd2(struct torture_context *tctx,
578 const void *test_data)
580 struct test_event_fd2_state state;
581 int sock[2];
582 uint8_t c = 0;
584 ZERO_STRUCT(state);
585 state.tctx = tctx;
586 state.backend = (const char *)test_data;
588 state.ev = tevent_context_init_byname(tctx, state.backend);
589 if (state.ev == NULL) {
590 torture_skip(tctx, talloc_asprintf(tctx,
591 "event backend '%s' not supported\n",
592 state.backend));
593 return true;
596 tevent_set_debug_stderr(state.ev);
597 torture_comment(tctx, "backend '%s' - %s\n",
598 state.backend, __FUNCTION__);
601 * This tests the following
603 * - We write 1 byte to each socket
604 * - We wait for TEVENT_FD_READ/WRITE on both sockets
605 * - When we get TEVENT_FD_WRITE we write 1 byte
606 * until both socket buffers are full, which
607 * means both sockets only get TEVENT_FD_READ.
608 * - Then we read 1 byte until we have consumed
609 * all bytes the other end has written.
611 sock[0] = -1;
612 sock[1] = -1;
613 socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
616 * the timer should never expire
618 state.te = tevent_add_timer(state.ev, state.ev,
619 timeval_current_ofs(600, 0),
620 test_event_fd2_finished, &state);
621 state.sock0.state = &state;
622 state.sock0.fd = sock[0];
623 state.sock0.fde = tevent_add_fd(state.ev, state.ev,
624 state.sock0.fd,
625 TEVENT_FD_READ | TEVENT_FD_WRITE,
626 test_event_fd2_sock_handler,
627 &state.sock0);
628 state.sock1.state = &state;
629 state.sock1.fd = sock[1];
630 state.sock1.fde = tevent_add_fd(state.ev, state.ev,
631 state.sock1.fd,
632 TEVENT_FD_READ | TEVENT_FD_WRITE,
633 test_event_fd2_sock_handler,
634 &state.sock1);
636 tevent_fd_set_auto_close(state.sock0.fde);
637 tevent_fd_set_auto_close(state.sock1.fde);
639 write(state.sock0.fd, &c, 1);
640 state.sock0.num_written++;
641 write(state.sock1.fd, &c, 1);
642 state.sock1.num_written++;
644 while (!state.finished) {
645 errno = 0;
646 if (tevent_loop_once(state.ev) == -1) {
647 talloc_free(state.ev);
648 torture_fail(tctx, talloc_asprintf(tctx,
649 "Failed event loop %s\n",
650 strerror(errno)));
654 talloc_free(state.ev);
656 torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
657 "%s", state.error));
659 return true;
662 #ifdef HAVE_PTHREAD
664 static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
665 static bool do_shutdown = false;
667 static void test_event_threaded_lock(void)
669 int ret;
670 ret = pthread_mutex_lock(&threaded_mutex);
671 assert(ret == 0);
674 static void test_event_threaded_unlock(void)
676 int ret;
677 ret = pthread_mutex_unlock(&threaded_mutex);
678 assert(ret == 0);
681 static void test_event_threaded_trace(enum tevent_trace_point point,
682 void *private_data)
684 switch (point) {
685 case TEVENT_TRACE_BEFORE_WAIT:
686 test_event_threaded_unlock();
687 break;
688 case TEVENT_TRACE_AFTER_WAIT:
689 test_event_threaded_lock();
690 break;
691 case TEVENT_TRACE_BEFORE_LOOP_ONCE:
692 case TEVENT_TRACE_AFTER_LOOP_ONCE:
693 break;
697 static void test_event_threaded_timer(struct tevent_context *ev,
698 struct tevent_timer *te,
699 struct timeval current_time,
700 void *private_data)
702 return;
705 static void *test_event_poll_thread(void *private_data)
707 struct tevent_context *ev = (struct tevent_context *)private_data;
709 test_event_threaded_lock();
711 while (true) {
712 int ret;
713 ret = tevent_loop_once(ev);
714 assert(ret == 0);
715 if (do_shutdown) {
716 test_event_threaded_unlock();
717 return NULL;
723 static void test_event_threaded_read_handler(struct tevent_context *ev,
724 struct tevent_fd *fde,
725 uint16_t flags,
726 void *private_data)
728 int *pfd = (int *)private_data;
729 char c;
730 ssize_t nread;
732 if ((flags & TEVENT_FD_READ) == 0) {
733 return;
736 do {
737 nread = read(*pfd, &c, 1);
738 } while ((nread == -1) && (errno == EINTR));
740 assert(nread == 1);
743 static bool test_event_context_threaded(struct torture_context *test,
744 const void *test_data)
746 struct tevent_context *ev;
747 struct tevent_timer *te;
748 struct tevent_fd *fde;
749 pthread_t poll_thread;
750 int fds[2];
751 int ret;
752 char c = 0;
754 ev = tevent_context_init_byname(test, "poll_mt");
755 torture_assert(test, ev != NULL, "poll_mt not supported");
757 tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
759 te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
760 test_event_threaded_timer, NULL);
761 torture_assert(test, te != NULL, "Could not add timer");
763 ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
764 torture_assert(test, ret == 0, "Could not create poll thread");
766 ret = pipe(fds);
767 torture_assert(test, ret == 0, "Could not create pipe");
769 poll(NULL, 0, 100);
771 test_event_threaded_lock();
773 fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
774 test_event_threaded_read_handler, &fds[0]);
775 torture_assert(test, fde != NULL, "Could not add fd event");
777 test_event_threaded_unlock();
779 poll(NULL, 0, 100);
781 write(fds[1], &c, 1);
783 poll(NULL, 0, 100);
785 test_event_threaded_lock();
786 do_shutdown = true;
787 test_event_threaded_unlock();
789 write(fds[1], &c, 1);
791 ret = pthread_join(poll_thread, NULL);
792 torture_assert(test, ret == 0, "pthread_join failed");
794 return true;
797 #endif
799 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
801 struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
802 const char **list = tevent_backend_list(suite);
803 int i;
805 for (i=0;list && list[i];i++) {
806 struct torture_suite *backend_suite;
808 backend_suite = torture_suite_create(mem_ctx, list[i]);
810 torture_suite_add_simple_tcase_const(backend_suite,
811 "context",
812 test_event_context,
813 (const void *)list[i]);
814 torture_suite_add_simple_tcase_const(backend_suite,
815 "fd1",
816 test_event_fd1,
817 (const void *)list[i]);
818 torture_suite_add_simple_tcase_const(backend_suite,
819 "fd2",
820 test_event_fd2,
821 (const void *)list[i]);
823 torture_suite_add_suite(suite, backend_suite);
826 #ifdef HAVE_PTHREAD
827 torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt",
828 test_event_context_threaded,
829 NULL);
830 #endif
832 return suite;