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
;
78 struct tevent_signal
*se2
= NULL
;
81 struct tevent_signal
*se3
= NULL
;
87 ev_ctx
= tevent_context_init_byname(test
, backend
);
89 torture_comment(test
, "event backend '%s' not supported\n", backend
);
93 torture_comment(test
, "backend '%s' - %s\n",
94 backend
, __FUNCTION__
);
102 fde
= tevent_add_fd(ev_ctx
, ev_ctx
, fd
[0], TEVENT_FD_READ
,
104 tevent_fd_set_auto_close(fde
);
106 tevent_add_timer(ev_ctx
, ev_ctx
, timeval_current_ofs(2,0),
107 finished_handler
, &finished
);
110 se1
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESTART
, count_handler
, &alarm_count
);
111 torture_assert(test
, se1
!= NULL
, "failed to setup se1");
114 se2
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGALRM
, SA_RESETHAND
, count_handler
, &alarm_count
);
115 torture_assert(test
, se2
!= NULL
, "failed to setup se2");
118 se3
= tevent_add_signal(ev_ctx
, ev_ctx
, SIGUSR1
, SA_SIGINFO
, count_handler
, &info_count
);
119 torture_assert(test
, se3
!= NULL
, "failed to setup se3");
124 t
= timeval_current();
127 if (tevent_loop_once(ev_ctx
) == -1) {
129 torture_fail(test
, talloc_asprintf(test
, "Failed event loop %s\n", strerror(errno
)));
136 while (alarm_count
< fde_count
+1) {
137 if (tevent_loop_once(ev_ctx
) == -1) {
142 torture_comment(test
, "Got %.2f pipe events/sec\n", fde_count
/timeval_elapsed(&t
));
148 torture_assert_int_equal(test
, alarm_count
, 1+fde_count
, "alarm count mismatch");
152 * we do not call talloc_free(se2)
153 * because it is already gone,
154 * after triggering the event handler.
160 torture_assert_int_equal(test
, info_count
, fde_count
, "info count mismatch");
170 static pthread_mutex_t threaded_mutex
= PTHREAD_MUTEX_INITIALIZER
;
171 static bool do_shutdown
= false;
173 static void test_event_threaded_lock(void)
176 ret
= pthread_mutex_lock(&threaded_mutex
);
180 static void test_event_threaded_unlock(void)
183 ret
= pthread_mutex_unlock(&threaded_mutex
);
187 static void test_event_threaded_trace(enum tevent_trace_point point
,
191 case TEVENT_TRACE_BEFORE_WAIT
:
192 test_event_threaded_unlock();
194 case TEVENT_TRACE_AFTER_WAIT
:
195 test_event_threaded_lock();
197 case TEVENT_TRACE_BEFORE_LOOP_ONCE
:
198 case TEVENT_TRACE_AFTER_LOOP_ONCE
:
203 static void test_event_threaded_timer(struct tevent_context
*ev
,
204 struct tevent_timer
*te
,
205 struct timeval current_time
,
211 static void *test_event_poll_thread(void *private_data
)
213 struct tevent_context
*ev
= (struct tevent_context
*)private_data
;
215 test_event_threaded_lock();
219 ret
= tevent_loop_once(ev
);
222 test_event_threaded_unlock();
229 static void test_event_threaded_read_handler(struct tevent_context
*ev
,
230 struct tevent_fd
*fde
,
234 int *pfd
= (int *)private_data
;
238 if ((flags
& TEVENT_FD_READ
) == 0) {
243 nread
= read(*pfd
, &c
, 1);
244 } while ((nread
== -1) && (errno
== EINTR
));
249 static bool test_event_context_threaded(struct torture_context
*test
,
250 const void *test_data
)
252 struct tevent_context
*ev
;
253 struct tevent_timer
*te
;
254 struct tevent_fd
*fde
;
255 pthread_t poll_thread
;
260 ev
= tevent_context_init_byname(test
, "poll_mt");
261 torture_assert(test
, ev
!= NULL
, "poll_mt not supported");
263 tevent_set_trace_callback(ev
, test_event_threaded_trace
, NULL
);
265 te
= tevent_add_timer(ev
, ev
, timeval_current_ofs(5, 0),
266 test_event_threaded_timer
, NULL
);
267 torture_assert(test
, te
!= NULL
, "Could not add timer");
269 ret
= pthread_create(&poll_thread
, NULL
, test_event_poll_thread
, ev
);
270 torture_assert(test
, ret
== 0, "Could not create poll thread");
273 torture_assert(test
, ret
== 0, "Could not create pipe");
277 test_event_threaded_lock();
279 fde
= tevent_add_fd(ev
, ev
, fds
[0], TEVENT_FD_READ
,
280 test_event_threaded_read_handler
, &fds
[0]);
281 torture_assert(test
, fde
!= NULL
, "Could not add fd event");
283 test_event_threaded_unlock();
287 write(fds
[1], &c
, 1);
291 test_event_threaded_lock();
293 test_event_threaded_unlock();
295 write(fds
[1], &c
, 1);
297 ret
= pthread_join(poll_thread
, NULL
);
298 torture_assert(test
, ret
== 0, "pthread_join failed");
305 struct torture_suite
*torture_local_event(TALLOC_CTX
*mem_ctx
)
307 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "event");
308 const char **list
= tevent_backend_list(suite
);
311 for (i
=0;list
&& list
[i
];i
++) {
312 torture_suite_add_simple_tcase_const(suite
, list
[i
],
314 (const void *)list
[i
]);
318 torture_suite_add_simple_tcase_const(suite
, "poll_mt_threaded",
319 test_event_context_threaded
,