auth/gensec: add support for SEC_CHAN_DNS_DOMAIN to schannel_update()
[obnox/samba/samba-obnox.git] / lib / tevent / testsuite.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    testing of the events subsystem
5
6    Copyright (C) Stefan Metzmacher 2006-2009
7    Copyright (C) Jeremy Allison    2013
8
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
12
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.
17
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.
22
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/>.
25 */
26
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 #include "torture/local/proto.h"
34 #ifdef HAVE_PTHREAD
35 #include <pthread.h>
36 #include <assert.h>
37 #endif
38
39 static int fde_count;
40
41 static void fde_handler_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
42                         uint16_t flags, void *private_data)
43 {
44         int *fd = (int *)private_data;
45         char c;
46 #ifdef SA_SIGINFO
47         kill(getpid(), SIGUSR1);
48 #endif
49         kill(getpid(), SIGALRM);
50
51         read(fd[0], &c, 1);
52         fde_count++;
53 }
54
55 static void fde_handler_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
56                         uint16_t flags, void *private_data)
57 {
58         int *fd = (int *)private_data;
59         char c = 0;
60         write(fd[1], &c, 1);
61 }
62
63
64 /* This will only fire if the fd's returned from pipe() are bi-directional. */
65 static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
66                         uint16_t flags, void *private_data)
67 {
68         int *fd = (int *)private_data;
69         char c;
70 #ifdef SA_SIGINFO
71         kill(getpid(), SIGUSR1);
72 #endif
73         kill(getpid(), SIGALRM);
74
75         read(fd[1], &c, 1);
76         fde_count++;
77 }
78
79 /* This will only fire if the fd's returned from pipe() are bi-directional. */
80 static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
81                         uint16_t flags, void *private_data)
82 {
83         int *fd = (int *)private_data;
84         char c = 0;
85         write(fd[0], &c, 1);
86 }
87
88 static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
89                              struct timeval tval, void *private_data)
90 {
91         int *finished = (int *)private_data;
92         (*finished) = 1;
93 }
94
95 static void count_handler(struct tevent_context *ev_ctx, struct tevent_signal *te,
96                           int signum, int count, void *info, void *private_data)
97 {
98         int *countp = (int *)private_data;
99         (*countp) += count;
100 }
101
102 static bool test_event_context(struct torture_context *test,
103                                const void *test_data)
104 {
105         struct tevent_context *ev_ctx;
106         int fd[2] = { -1, -1 };
107         const char *backend = (const char *)test_data;
108         int alarm_count=0, info_count=0;
109         struct tevent_fd *fde_read;
110         struct tevent_fd *fde_read_1;
111         struct tevent_fd *fde_write;
112         struct tevent_fd *fde_write_1;
113 #ifdef SA_RESTART
114         struct tevent_signal *se1 = NULL;
115 #endif
116 #ifdef SA_RESETHAND
117         struct tevent_signal *se2 = NULL;
118 #endif
119 #ifdef SA_SIGINFO
120         struct tevent_signal *se3 = NULL;
121 #endif
122         int finished=0;
123         struct timeval t;
124
125         ev_ctx = tevent_context_init_byname(test, backend);
126         if (ev_ctx == NULL) {
127                 torture_comment(test, "event backend '%s' not supported\n", backend);
128                 return true;
129         }
130
131         torture_comment(test, "backend '%s' - %s\n",
132                         backend, __FUNCTION__);
133
134         /* reset globals */
135         fde_count = 0;
136
137         /* create a pipe */
138         pipe(fd);
139
140         fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
141                             fde_handler_read, fd);
142         fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
143                             fde_handler_write_1, fd);
144
145         fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
146                             fde_handler_write, fd);
147         fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
148                             fde_handler_read_1, fd);
149
150         tevent_fd_set_auto_close(fde_read);
151         tevent_fd_set_auto_close(fde_write);
152
153         tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0),
154                          finished_handler, &finished);
155
156 #ifdef SA_RESTART
157         se1 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
158         torture_assert(test, se1 != NULL, "failed to setup se1");
159 #endif
160 #ifdef SA_RESETHAND
161         se2 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
162         torture_assert(test, se2 != NULL, "failed to setup se2");
163 #endif
164 #ifdef SA_SIGINFO
165         se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
166         torture_assert(test, se3 != NULL, "failed to setup se3");
167 #endif
168
169         t = timeval_current();
170         while (!finished) {
171                 errno = 0;
172                 if (tevent_loop_once(ev_ctx) == -1) {
173                         talloc_free(ev_ctx);
174                         torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
175                 }
176         }
177
178         talloc_free(fde_read);
179         talloc_free(fde_write);
180         talloc_free(fde_read_1);
181         talloc_free(fde_write_1);
182
183         while (alarm_count < fde_count+1) {
184                 if (tevent_loop_once(ev_ctx) == -1) {
185                         break;
186                 }
187         }
188
189         torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
190
191 #ifdef SA_RESTART
192         talloc_free(se1);
193 #endif
194
195         torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
196
197 #ifdef SA_RESETHAND
198         /*
199          * we do not call talloc_free(se2)
200          * because it is already gone,
201          * after triggering the event handler.
202          */
203 #endif
204
205 #ifdef SA_SIGINFO
206         talloc_free(se3);
207         torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
208 #endif
209
210         talloc_free(ev_ctx);
211
212         return true;
213 }
214
215 struct test_event_fd1_state {
216         struct torture_context *tctx;
217         const char *backend;
218         struct tevent_context *ev;
219         int sock[2];
220         struct tevent_timer *te;
221         struct tevent_fd *fde0;
222         struct tevent_fd *fde1;
223         bool got_write;
224         bool got_read;
225         bool drain;
226         bool drain_done;
227         unsigned loop_count;
228         bool finished;
229         const char *error;
230 };
231
232 static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx,
233                                        struct tevent_fd *fde,
234                                        uint16_t flags,
235                                        void *private_data)
236 {
237         struct test_event_fd1_state *state =
238                 (struct test_event_fd1_state *)private_data;
239
240         if (state->drain_done) {
241                 state->finished = true;
242                 state->error = __location__;
243                 return;
244         }
245
246         if (state->drain) {
247                 ssize_t ret;
248                 uint8_t c = 0;
249
250                 if (!(flags & TEVENT_FD_READ)) {
251                         state->finished = true;
252                         state->error = __location__;
253                         return;
254                 }
255
256                 ret = read(state->sock[0], &c, 1);
257                 if (ret == 1) {
258                         return;
259                 }
260
261                 /*
262                  * end of test...
263                  */
264                 tevent_fd_set_flags(fde, 0);
265                 state->drain_done = true;
266                 return;
267         }
268
269         if (!state->got_write) {
270                 uint8_t c = 0;
271
272                 if (flags != TEVENT_FD_WRITE) {
273                         state->finished = true;
274                         state->error = __location__;
275                         return;
276                 }
277                 state->got_write = true;
278
279                 /*
280                  * we write to the other socket...
281                  */
282                 write(state->sock[1], &c, 1);
283                 TEVENT_FD_NOT_WRITEABLE(fde);
284                 TEVENT_FD_READABLE(fde);
285                 return;
286         }
287
288         if (!state->got_read) {
289                 if (flags != TEVENT_FD_READ) {
290                         state->finished = true;
291                         state->error = __location__;
292                         return;
293                 }
294                 state->got_read = true;
295
296                 TEVENT_FD_NOT_READABLE(fde);
297                 return;
298         }
299
300         state->finished = true;
301         state->error = __location__;
302         return;
303 }
304
305 static void test_event_fd1_finished(struct tevent_context *ev_ctx,
306                                     struct tevent_timer *te,
307                                     struct timeval tval,
308                                     void *private_data)
309 {
310         struct test_event_fd1_state *state =
311                 (struct test_event_fd1_state *)private_data;
312
313         if (state->drain_done) {
314                 state->finished = true;
315                 return;
316         }
317
318         if (!state->got_write) {
319                 state->finished = true;
320                 state->error = __location__;
321                 return;
322         }
323
324         if (!state->got_read) {
325                 state->finished = true;
326                 state->error = __location__;
327                 return;
328         }
329
330         state->loop_count++;
331         if (state->loop_count > 3) {
332                 state->finished = true;
333                 state->error = __location__;
334                 return;
335         }
336
337         state->got_write = false;
338         state->got_read = false;
339
340         tevent_fd_set_flags(state->fde0, TEVENT_FD_WRITE);
341
342         if (state->loop_count > 2) {
343                 state->drain = true;
344                 TALLOC_FREE(state->fde1);
345                 TEVENT_FD_READABLE(state->fde0);
346         }
347
348         state->te = tevent_add_timer(state->ev, state->ev,
349                                     timeval_current_ofs(0,2000),
350                                     test_event_fd1_finished, state);
351 }
352
353 static bool test_event_fd1(struct torture_context *tctx,
354                            const void *test_data)
355 {
356         struct test_event_fd1_state state;
357
358         ZERO_STRUCT(state);
359         state.tctx = tctx;
360         state.backend = (const char *)test_data;
361
362         state.ev = tevent_context_init_byname(tctx, state.backend);
363         if (state.ev == NULL) {
364                 torture_skip(tctx, talloc_asprintf(tctx,
365                              "event backend '%s' not supported\n",
366                              state.backend));
367                 return true;
368         }
369
370         tevent_set_debug_stderr(state.ev);
371         torture_comment(tctx, "backend '%s' - %s\n",
372                         state.backend, __FUNCTION__);
373
374         /*
375          * This tests the following:
376          *
377          * It monitors the state of state.sock[0]
378          * with tevent_fd, but we never read/write on state.sock[0]
379          * while state.sock[1] * is only used to write a few bytes.
380          *
381          * We have a loop:
382          *   - we wait only for TEVENT_FD_WRITE on state.sock[0]
383          *   - we write 1 byte to state.sock[1]
384          *   - we wait only for TEVENT_FD_READ on state.sock[0]
385          *   - we disable events on state.sock[0]
386          *   - the timer event restarts the loop
387          * Then we close state.sock[1]
388          * We have a loop:
389          *   - we wait for TEVENT_FD_READ/WRITE on state.sock[0]
390          *   - we try to read 1 byte
391          *   - if the read gets an error of returns 0
392          *     we disable the event handler
393          *   - the timer finishes the test
394          */
395         state.sock[0] = -1;
396         state.sock[1] = -1;
397         socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock);
398
399         state.te = tevent_add_timer(state.ev, state.ev,
400                                     timeval_current_ofs(0,1000),
401                                     test_event_fd1_finished, &state);
402         state.fde0 = tevent_add_fd(state.ev, state.ev,
403                                    state.sock[0], TEVENT_FD_WRITE,
404                                    test_event_fd1_fde_handler, &state);
405         /* state.fde1 is only used to auto close */
406         state.fde1 = tevent_add_fd(state.ev, state.ev,
407                                    state.sock[1], 0,
408                                    test_event_fd1_fde_handler, &state);
409
410         tevent_fd_set_auto_close(state.fde0);
411         tevent_fd_set_auto_close(state.fde1);
412
413         while (!state.finished) {
414                 errno = 0;
415                 if (tevent_loop_once(state.ev) == -1) {
416                         talloc_free(state.ev);
417                         torture_fail(tctx, talloc_asprintf(tctx,
418                                      "Failed event loop %s\n",
419                                      strerror(errno)));
420                 }
421         }
422
423         talloc_free(state.ev);
424
425         torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
426                        "%s", state.error));
427
428         return true;
429 }
430
431 struct test_event_fd2_state {
432         struct torture_context *tctx;
433         const char *backend;
434         struct tevent_context *ev;
435         struct tevent_timer *te;
436         struct test_event_fd2_sock {
437                 struct test_event_fd2_state *state;
438                 int fd;
439                 struct tevent_fd *fde;
440                 size_t num_written;
441                 size_t num_read;
442                 bool got_full;
443         } sock0, sock1;
444         bool finished;
445         const char *error;
446 };
447
448 static void test_event_fd2_sock_handler(struct tevent_context *ev_ctx,
449                                         struct tevent_fd *fde,
450                                         uint16_t flags,
451                                         void *private_data)
452 {
453         struct test_event_fd2_sock *cur_sock =
454                 (struct test_event_fd2_sock *)private_data;
455         struct test_event_fd2_state *state = cur_sock->state;
456         struct test_event_fd2_sock *oth_sock = NULL;
457         uint8_t v = 0, c;
458         ssize_t ret;
459
460         if (cur_sock == &state->sock0) {
461                 oth_sock = &state->sock1;
462         } else {
463                 oth_sock = &state->sock0;
464         }
465
466         if (oth_sock->num_written == 1) {
467                 if (flags != (TEVENT_FD_READ | TEVENT_FD_WRITE)) {
468                         state->finished = true;
469                         state->error = __location__;
470                         return;
471                 }
472         }
473
474         if (cur_sock->num_read == oth_sock->num_written) {
475                 state->finished = true;
476                 state->error = __location__;
477                 return;
478         }
479
480         if (!(flags & TEVENT_FD_READ)) {
481                 state->finished = true;
482                 state->error = __location__;
483                 return;
484         }
485
486         if (oth_sock->num_read >= PIPE_BUF) {
487                 /*
488                  * On Linux we become writable once we've read
489                  * one byte. On Solaris we only become writable
490                  * again once we've read 4096 bytes. PIPE_BUF
491                  * is probably a safe bet to test against.
492                  *
493                  * There should be room to write a byte again
494                  */
495                 if (!(flags & TEVENT_FD_WRITE)) {
496                         state->finished = true;
497                         state->error = __location__;
498                         return;
499                 }
500         }
501
502         if ((flags & TEVENT_FD_WRITE) && !cur_sock->got_full) {
503                 v = (uint8_t)cur_sock->num_written;
504                 ret = write(cur_sock->fd, &v, 1);
505                 if (ret != 1) {
506                         state->finished = true;
507                         state->error = __location__;
508                         return;
509                 }
510                 cur_sock->num_written++;
511                 if (cur_sock->num_written > 0x80000000) {
512                         state->finished = true;
513                         state->error = __location__;
514                         return;
515                 }
516                 return;
517         }
518
519         if (!cur_sock->got_full) {
520                 cur_sock->got_full = true;
521
522                 if (!oth_sock->got_full) {
523                         /*
524                          * cur_sock is full,
525                          * lets wait for oth_sock
526                          * to be filled
527                          */
528                         tevent_fd_set_flags(cur_sock->fde, 0);
529                         return;
530                 }
531
532                 /*
533                  * oth_sock waited for cur_sock,
534                  * lets restart it
535                  */
536                 tevent_fd_set_flags(oth_sock->fde,
537                                     TEVENT_FD_READ|TEVENT_FD_WRITE);
538         }
539
540         ret = read(cur_sock->fd, &v, 1);
541         if (ret != 1) {
542                 state->finished = true;
543                 state->error = __location__;
544                 return;
545         }
546         c = (uint8_t)cur_sock->num_read;
547         if (c != v) {
548                 state->finished = true;
549                 state->error = __location__;
550                 return;
551         }
552         cur_sock->num_read++;
553
554         if (cur_sock->num_read < oth_sock->num_written) {
555                 /* there is more to read */
556                 return;
557         }
558         /*
559          * we read everything, we need to remove TEVENT_FD_WRITE
560          * to avoid spinning
561          */
562         TEVENT_FD_NOT_WRITEABLE(cur_sock->fde);
563
564         if (oth_sock->num_read == cur_sock->num_written) {
565                 /*
566                  * both directions are finished
567                  */
568                 state->finished = true;
569         }
570
571         return;
572 }
573
574 static void test_event_fd2_finished(struct tevent_context *ev_ctx,
575                                     struct tevent_timer *te,
576                                     struct timeval tval,
577                                     void *private_data)
578 {
579         struct test_event_fd2_state *state =
580                 (struct test_event_fd2_state *)private_data;
581
582         /*
583          * this should never be triggered
584          */
585         state->finished = true;
586         state->error = __location__;
587 }
588
589 static bool test_event_fd2(struct torture_context *tctx,
590                            const void *test_data)
591 {
592         struct test_event_fd2_state state;
593         int sock[2];
594         uint8_t c = 0;
595
596         ZERO_STRUCT(state);
597         state.tctx = tctx;
598         state.backend = (const char *)test_data;
599
600         state.ev = tevent_context_init_byname(tctx, state.backend);
601         if (state.ev == NULL) {
602                 torture_skip(tctx, talloc_asprintf(tctx,
603                              "event backend '%s' not supported\n",
604                              state.backend));
605                 return true;
606         }
607
608         tevent_set_debug_stderr(state.ev);
609         torture_comment(tctx, "backend '%s' - %s\n",
610                         state.backend, __FUNCTION__);
611
612         /*
613          * This tests the following
614          *
615          * - We write 1 byte to each socket
616          * - We wait for TEVENT_FD_READ/WRITE on both sockets
617          * - When we get TEVENT_FD_WRITE we write 1 byte
618          *   until both socket buffers are full, which
619          *   means both sockets only get TEVENT_FD_READ.
620          * - Then we read 1 byte until we have consumed
621          *   all bytes the other end has written.
622          */
623         sock[0] = -1;
624         sock[1] = -1;
625         socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
626
627         /*
628          * the timer should never expire
629          */
630         state.te = tevent_add_timer(state.ev, state.ev,
631                                     timeval_current_ofs(600, 0),
632                                     test_event_fd2_finished, &state);
633         state.sock0.state = &state;
634         state.sock0.fd = sock[0];
635         state.sock0.fde = tevent_add_fd(state.ev, state.ev,
636                                         state.sock0.fd,
637                                         TEVENT_FD_READ | TEVENT_FD_WRITE,
638                                         test_event_fd2_sock_handler,
639                                         &state.sock0);
640         state.sock1.state = &state;
641         state.sock1.fd = sock[1];
642         state.sock1.fde = tevent_add_fd(state.ev, state.ev,
643                                         state.sock1.fd,
644                                         TEVENT_FD_READ | TEVENT_FD_WRITE,
645                                         test_event_fd2_sock_handler,
646                                         &state.sock1);
647
648         tevent_fd_set_auto_close(state.sock0.fde);
649         tevent_fd_set_auto_close(state.sock1.fde);
650
651         write(state.sock0.fd, &c, 1);
652         state.sock0.num_written++;
653         write(state.sock1.fd, &c, 1);
654         state.sock1.num_written++;
655
656         while (!state.finished) {
657                 errno = 0;
658                 if (tevent_loop_once(state.ev) == -1) {
659                         talloc_free(state.ev);
660                         torture_fail(tctx, talloc_asprintf(tctx,
661                                      "Failed event loop %s\n",
662                                      strerror(errno)));
663                 }
664         }
665
666         talloc_free(state.ev);
667
668         torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
669                        "%s", state.error));
670
671         return true;
672 }
673
674 #ifdef HAVE_PTHREAD
675
676 static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
677 static bool do_shutdown = false;
678
679 static void test_event_threaded_lock(void)
680 {
681         int ret;
682         ret = pthread_mutex_lock(&threaded_mutex);
683         assert(ret == 0);
684 }
685
686 static void test_event_threaded_unlock(void)
687 {
688         int ret;
689         ret = pthread_mutex_unlock(&threaded_mutex);
690         assert(ret == 0);
691 }
692
693 static void test_event_threaded_trace(enum tevent_trace_point point,
694                                       void *private_data)
695 {
696         switch (point) {
697         case TEVENT_TRACE_BEFORE_WAIT:
698                 test_event_threaded_unlock();
699                 break;
700         case TEVENT_TRACE_AFTER_WAIT:
701                 test_event_threaded_lock();
702                 break;
703         case TEVENT_TRACE_BEFORE_LOOP_ONCE:
704         case TEVENT_TRACE_AFTER_LOOP_ONCE:
705                 break;
706         }
707 }
708
709 static void test_event_threaded_timer(struct tevent_context *ev,
710                                       struct tevent_timer *te,
711                                       struct timeval current_time,
712                                       void *private_data)
713 {
714         return;
715 }
716
717 static void *test_event_poll_thread(void *private_data)
718 {
719         struct tevent_context *ev = (struct tevent_context *)private_data;
720
721         test_event_threaded_lock();
722
723         while (true) {
724                 int ret;
725                 ret = tevent_loop_once(ev);
726                 assert(ret == 0);
727                 if (do_shutdown) {
728                         test_event_threaded_unlock();
729                         return NULL;
730                 }
731         }
732
733 }
734
735 static void test_event_threaded_read_handler(struct tevent_context *ev,
736                                              struct tevent_fd *fde,
737                                              uint16_t flags,
738                                              void *private_data)
739 {
740         int *pfd = (int *)private_data;
741         char c;
742         ssize_t nread;
743
744         if ((flags & TEVENT_FD_READ) == 0) {
745                 return;
746         }
747
748         do {
749                 nread = read(*pfd, &c, 1);
750         } while ((nread == -1) && (errno == EINTR));
751
752         assert(nread == 1);
753 }
754
755 static bool test_event_context_threaded(struct torture_context *test,
756                                         const void *test_data)
757 {
758         struct tevent_context *ev;
759         struct tevent_timer *te;
760         struct tevent_fd *fde;
761         pthread_t poll_thread;
762         int fds[2];
763         int ret;
764         char c = 0;
765
766         ev = tevent_context_init_byname(test, "poll_mt");
767         torture_assert(test, ev != NULL, "poll_mt not supported");
768
769         tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
770
771         te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
772                               test_event_threaded_timer, NULL);
773         torture_assert(test, te != NULL, "Could not add timer");
774
775         ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
776         torture_assert(test, ret == 0, "Could not create poll thread");
777
778         ret = pipe(fds);
779         torture_assert(test, ret == 0, "Could not create pipe");
780
781         poll(NULL, 0, 100);
782
783         test_event_threaded_lock();
784
785         fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
786                             test_event_threaded_read_handler, &fds[0]);
787         torture_assert(test, fde != NULL, "Could not add fd event");
788
789         test_event_threaded_unlock();
790
791         poll(NULL, 0, 100);
792
793         write(fds[1], &c, 1);
794
795         poll(NULL, 0, 100);
796
797         test_event_threaded_lock();
798         do_shutdown = true;
799         test_event_threaded_unlock();
800
801         write(fds[1], &c, 1);
802
803         ret = pthread_join(poll_thread, NULL);
804         torture_assert(test, ret == 0, "pthread_join failed");
805
806         return true;
807 }
808
809 #endif
810
811 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
812 {
813         struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
814         const char **list = tevent_backend_list(suite);
815         int i;
816
817         for (i=0;list && list[i];i++) {
818                 struct torture_suite *backend_suite;
819
820                 backend_suite = torture_suite_create(mem_ctx, list[i]);
821
822                 torture_suite_add_simple_tcase_const(backend_suite,
823                                                "context",
824                                                test_event_context,
825                                                (const void *)list[i]);
826                 torture_suite_add_simple_tcase_const(backend_suite,
827                                                "fd1",
828                                                test_event_fd1,
829                                                (const void *)list[i]);
830                 torture_suite_add_simple_tcase_const(backend_suite,
831                                                "fd2",
832                                                test_event_fd2,
833                                                (const void *)list[i]);
834
835                 torture_suite_add_suite(suite, backend_suite);
836         }
837
838 #ifdef HAVE_PTHREAD
839         torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt",
840                                              test_event_context_threaded,
841                                              NULL);
842 #endif
843
844         return suite;
845 }