2 Unix SMB/CIFS implementation.
4 testing of the events subsystem
6 Copyright (C) Stefan Metzmacher 2006-2009
8 ** NOTE! The following LGPL license applies to the tevent
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "lib/tevent/tevent.h"
28 #include "system/filesys.h"
29 #include "system/select.h"
30 #include "torture/torture.h"
38 static void fde_handler(struct tevent_context
*ev_ctx
, struct tevent_fd
*f
,
39 uint16_t flags
, void *private_data
)
41 int *fd
= (int *)private_data
;
44 kill(getpid(), SIGUSR1
);
46 kill(getpid(), SIGALRM
);
52 static void finished_handler(struct tevent_context
*ev_ctx
, struct tevent_timer
*te
,
53 struct timeval tval
, void *private_data
)
55 int *finished
= (int *)private_data
;
59 static void count_handler(struct tevent_context
*ev_ctx
, struct tevent_signal
*te
,
60 int signum
, int count
, void *info
, void *private_data
)
62 int *countp
= (int *)private_data
;
66 static bool test_event_context(struct torture_context
*test
,
67 const void *test_data
)
69 struct tevent_context
*ev_ctx
;
70 int fd
[2] = { -1, -1 };
71 const char *backend
= (const char *)test_data
;
72 int alarm_count
=0, info_count
=0;
73 struct tevent_fd
*fde
;
75 struct tevent_signal
*se1
= NULL
;
77 struct tevent_signal
*se2
= NULL
;
79 struct tevent_signal
*se3
= NULL
;
85 ev_ctx
= tevent_context_init_byname(test
, backend
);
87 torture_comment(test
, "event backend '%s' not supported\n", backend
);
91 torture_comment(test
, "Testing event backend '%s'\n", backend
);
99 fde
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[0], TEVENT_FD_READ
,
101 tevent_fd_set_auto_close(fde
);
103 tevent_add_timer(ev_ctx
, ev_ctx
, timeval_current_ofs(2,0),
104 finished_handler
, &finished
);
107 se1
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESTART
, count_handler
, &alarm_count
);
110 se2
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESETHAND
, count_handler
, &alarm_count
);
113 se3
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGUSR1
, SA_SIGINFO
, count_handler
, &info_count
);
118 t
= timeval_current();
121 if (tevent_loop_once(ev_ctx
) == -1) {
123 torture_fail(test
, talloc_asprintf(test
, "Failed event loop %s\n", strerror(errno
)));
130 while (alarm_count
< fde_count
+1) {
131 if (tevent_loop_once(ev_ctx
) == -1) {
136 torture_comment(test
, "Got %.2f pipe events/sec\n", fde_count
/timeval_elapsed(&t
));
142 torture_assert_int_equal(test
, alarm_count
, 1+fde_count
, "alarm count mismatch");
146 torture_assert_int_equal(test
, info_count
, fde_count
, "info count mismatch");
156 static pthread_mutex_t threaded_mutex
= PTHREAD_MUTEX_INITIALIZER
;
157 static bool do_shutdown
= false;
159 static void test_event_threaded_lock(void)
162 ret
= pthread_mutex_lock(&threaded_mutex
);
166 static void test_event_threaded_unlock(void)
169 ret
= pthread_mutex_unlock(&threaded_mutex
);
173 static void test_event_threaded_trace(enum tevent_trace_point point
,
177 case TEVENT_TRACE_BEFORE_WAIT
:
178 test_event_threaded_unlock();
180 case TEVENT_TRACE_AFTER_WAIT
:
181 test_event_threaded_lock();
186 static void test_event_threaded_timer(struct tevent_context
*ev
,
187 struct tevent_timer
*te
,
188 struct timeval current_time
,
194 static void *test_event_poll_thread(void *private_data
)
196 struct tevent_context
*ev
= (struct tevent_context
*)private_data
;
198 test_event_threaded_lock();
202 ret
= tevent_loop_once(ev
);
205 test_event_threaded_unlock();
212 static void test_event_threaded_read_handler(struct tevent_context
*ev
,
213 struct tevent_fd
*fde
,
217 int *pfd
= (int *)private_data
;
221 if ((flags
& TEVENT_FD_READ
) == 0) {
226 nread
= read(*pfd
, &c
, 1);
227 } while ((nread
== -1) && (errno
== EINTR
));
232 static bool test_event_context_threaded(struct torture_context
*test
,
233 const void *test_data
)
235 struct tevent_context
*ev
;
236 struct tevent_timer
*te
;
237 struct tevent_fd
*fde
;
238 pthread_t poll_thread
;
243 ev
= tevent_context_init_byname(test
, "poll_mt");
244 torture_assert(test
, ev
!= NULL
, "poll_mt not supported");
246 tevent_set_trace_callback(ev
, test_event_threaded_trace
, NULL
);
248 te
= tevent_add_timer(ev
, ev
, timeval_current_ofs(5, 0),
249 test_event_threaded_timer
, NULL
);
250 torture_assert(test
, te
!= NULL
, "Could not add timer");
252 ret
= pthread_create(&poll_thread
, NULL
, test_event_poll_thread
, ev
);
253 torture_assert(test
, ret
== 0, "Could not create poll thread");
256 torture_assert(test
, ret
== 0, "Could not create pipe");
260 test_event_threaded_lock();
262 fde
= tevent_add_fd(ev
, ev
, fds
[0], TEVENT_FD_READ
,
263 test_event_threaded_read_handler
, &fds
[0]);
264 torture_assert(test
, fde
!= NULL
, "Could not add fd event");
266 test_event_threaded_unlock();
270 write(fds
[1], &c
, 1);
274 test_event_threaded_lock();
276 test_event_threaded_unlock();
278 write(fds
[1], &c
, 1);
280 ret
= pthread_join(poll_thread
, NULL
);
281 torture_assert(test
, ret
== 0, "pthread_join failed");
288 struct torture_suite
*torture_local_event(TALLOC_CTX
*mem_ctx
)
290 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "event");
291 const char **list
= tevent_backend_list(suite
);
294 for (i
=0;list
&& list
[i
];i
++) {
295 torture_suite_add_simple_tcase_const(suite
, list
[i
],
297 (const void *)list
[i
]);
301 torture_suite_add_simple_tcase_const(suite
, "poll_mt_threaded",
302 test_event_context_threaded
,