2 Unix SMB/CIFS implementation.
4 testing of the events subsystem
6 Copyright (C) Stefan Metzmacher 2006-2009
7 Copyright (C) Jeremy Allison 2013
9 ** NOTE! The following LGPL license applies to the tevent
10 ** library. This does NOT imply that all of Samba is released
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 3 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 #include "lib/tevent/tevent.h"
29 #include "system/filesys.h"
30 #include "system/select.h"
31 #include "torture/torture.h"
39 static void fde_handler_read(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
40 uint16_t flags
, void *private_data
)
42 int *fd
= (int *)private_data
;
45 kill(getpid(), SIGUSR1
);
47 kill(getpid(), SIGALRM
);
53 static void fde_handler_write(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
54 uint16_t flags
, void *private_data
)
56 int *fd
= (int *)private_data
;
62 /* These should never fire... */
63 static void fde_handler_read_1(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
64 uint16_t flags
, void *private_data
)
66 struct torture_context
*test
= (struct torture_context
*)private_data
;
67 torture_comment(test
, "fde_handler_read_1 should never fire !\n");
71 /* These should never fire... */
72 static void fde_handler_write_1(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
73 uint16_t flags
, void *private_data
)
75 struct torture_context
*test
= (struct torture_context
*)private_data
;
76 torture_comment(test
, "fde_handler_write_1 should never fire !\n");
80 static void finished_handler(struct tevent_context
*ev_ctx
, struct tevent_timer
*te
,
81 struct timeval tval
, void *private_data
)
83 int *finished
= (int *)private_data
;
87 static void count_handler(struct tevent_context
*ev_ctx
, struct tevent_signal
*te
,
88 int signum
, int count
, void *info
, void *private_data
)
90 int *countp
= (int *)private_data
;
94 static bool test_event_context(struct torture_context
*test
,
95 const void *test_data
)
97 struct tevent_context
*ev_ctx
;
98 int fd
[2] = { -1, -1 };
99 const char *backend
= (const char *)test_data
;
100 int alarm_count
=0, info_count
=0;
101 struct tevent_fd
*fde_read
;
102 struct tevent_fd
*fde_read_1
;
103 struct tevent_fd
*fde_write
;
104 struct tevent_fd
*fde_write_1
;
106 struct tevent_signal
*se1
= NULL
;
109 struct tevent_signal
*se2
= NULL
;
112 struct tevent_signal
*se3
= NULL
;
117 ev_ctx
= tevent_context_init_byname(test
, backend
);
118 if (ev_ctx
== NULL
) {
119 torture_comment(test
, "event backend '%s' not supported\n", backend
);
123 torture_comment(test
, "backend '%s' - %s\n",
124 backend
, __FUNCTION__
);
132 fde_read
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[0], TEVENT_FD_READ
,
133 fde_handler_read
, fd
);
134 fde_write_1
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[0], TEVENT_FD_WRITE
,
135 fde_handler_write_1
, test
);
137 fde_write
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[1], TEVENT_FD_WRITE
,
138 fde_handler_write
, fd
);
139 fde_read_1
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[1], TEVENT_FD_READ
,
140 fde_handler_read_1
, test
);
142 tevent_fd_set_auto_close(fde_read
);
143 tevent_fd_set_auto_close(fde_write
);
145 tevent_add_timer(ev_ctx
, ev_ctx
, timeval_current_ofs(2,0),
146 finished_handler
, &finished
);
149 se1
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESTART
, count_handler
, &alarm_count
);
150 torture_assert(test
, se1
!= NULL
, "failed to setup se1");
153 se2
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESETHAND
, count_handler
, &alarm_count
);
154 torture_assert(test
, se2
!= NULL
, "failed to setup se2");
157 se3
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGUSR1
, SA_SIGINFO
, count_handler
, &info_count
);
158 torture_assert(test
, se3
!= NULL
, "failed to setup se3");
161 t
= timeval_current();
164 if (tevent_loop_once(ev_ctx
) == -1) {
166 torture_fail(test
, talloc_asprintf(test
, "Failed event loop %s\n", strerror(errno
)));
170 talloc_free(fde_read
);
171 talloc_free(fde_write
);
172 talloc_free(fde_read_1
);
173 talloc_free(fde_write_1
);
175 while (alarm_count
< fde_count
+1) {
176 if (tevent_loop_once(ev_ctx
) == -1) {
181 torture_comment(test
, "Got %.2f pipe events/sec\n", fde_count
/timeval_elapsed(&t
));
187 torture_assert_int_equal(test
, alarm_count
, 1+fde_count
, "alarm count mismatch");
191 * we do not call talloc_free(se2)
192 * because it is already gone,
193 * after triggering the event handler.
199 torture_assert_int_equal(test
, info_count
, fde_count
, "info count mismatch");
209 static pthread_mutex_t threaded_mutex
= PTHREAD_MUTEX_INITIALIZER
;
210 static bool do_shutdown
= false;
212 static void test_event_threaded_lock(void)
215 ret
= pthread_mutex_lock(&threaded_mutex
);
219 static void test_event_threaded_unlock(void)
222 ret
= pthread_mutex_unlock(&threaded_mutex
);
226 static void test_event_threaded_trace(enum tevent_trace_point point
,
230 case TEVENT_TRACE_BEFORE_WAIT
:
231 test_event_threaded_unlock();
233 case TEVENT_TRACE_AFTER_WAIT
:
234 test_event_threaded_lock();
236 case TEVENT_TRACE_BEFORE_LOOP_ONCE
:
237 case TEVENT_TRACE_AFTER_LOOP_ONCE
:
242 static void test_event_threaded_timer(struct tevent_context
*ev
,
243 struct tevent_timer
*te
,
244 struct timeval current_time
,
250 static void *test_event_poll_thread(void *private_data
)
252 struct tevent_context
*ev
= (struct tevent_context
*)private_data
;
254 test_event_threaded_lock();
258 ret
= tevent_loop_once(ev
);
261 test_event_threaded_unlock();
268 static void test_event_threaded_read_handler(struct tevent_context
*ev
,
269 struct tevent_fd
*fde
,
273 int *pfd
= (int *)private_data
;
277 if ((flags
& TEVENT_FD_READ
) == 0) {
282 nread
= read(*pfd
, &c
, 1);
283 } while ((nread
== -1) && (errno
== EINTR
));
288 static bool test_event_context_threaded(struct torture_context
*test
,
289 const void *test_data
)
291 struct tevent_context
*ev
;
292 struct tevent_timer
*te
;
293 struct tevent_fd
*fde
;
294 pthread_t poll_thread
;
299 ev
= tevent_context_init_byname(test
, "poll_mt");
300 torture_assert(test
, ev
!= NULL
, "poll_mt not supported");
302 tevent_set_trace_callback(ev
, test_event_threaded_trace
, NULL
);
304 te
= tevent_add_timer(ev
, ev
, timeval_current_ofs(5, 0),
305 test_event_threaded_timer
, NULL
);
306 torture_assert(test
, te
!= NULL
, "Could not add timer");
308 ret
= pthread_create(&poll_thread
, NULL
, test_event_poll_thread
, ev
);
309 torture_assert(test
, ret
== 0, "Could not create poll thread");
312 torture_assert(test
, ret
== 0, "Could not create pipe");
316 test_event_threaded_lock();
318 fde
= tevent_add_fd(ev
, ev
, fds
[0], TEVENT_FD_READ
,
319 test_event_threaded_read_handler
, &fds
[0]);
320 torture_assert(test
, fde
!= NULL
, "Could not add fd event");
322 test_event_threaded_unlock();
326 write(fds
[1], &c
, 1);
330 test_event_threaded_lock();
332 test_event_threaded_unlock();
334 write(fds
[1], &c
, 1);
336 ret
= pthread_join(poll_thread
, NULL
);
337 torture_assert(test
, ret
== 0, "pthread_join failed");
344 struct torture_suite
*torture_local_event(TALLOC_CTX
*mem_ctx
)
346 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "event");
347 const char **list
= tevent_backend_list(suite
);
350 for (i
=0;list
&& list
[i
];i
++) {
351 torture_suite_add_simple_tcase_const(suite
, list
[i
],
353 (const void *)list
[i
]);
357 torture_suite_add_simple_tcase_const(suite
, "poll_mt_threaded",
358 test_event_context_threaded
,