faa18577a7acb3523520057ebe9176bbb9e00883
[jra/samba/.git] / lib / tevent / testsuite.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    testing of the events subsystem
5    
6    Copyright (C) Stefan Metzmacher
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/events/events.h"
24 #include "system/filesys.h"
25 #include "torture/torture.h"
26
27 static int fde_count;
28
29 static void fde_handler(struct tevent_context *ev_ctx, struct tevent_fd *f, 
30                         uint16_t flags, void *private_data)
31 {
32         int *fd = (int *)private_data;
33         char c;
34 #ifdef SA_SIGINFO
35         kill(getpid(), SIGUSR1);
36 #endif
37         kill(getpid(), SIGALRM);
38         read(fd[0], &c, 1);
39         write(fd[1], &c, 1);
40         fde_count++;
41 }
42
43 static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
44                              struct timeval tval, void *private_data)
45 {
46         int *finished = (int *)private_data;
47         (*finished) = 1;
48 }
49
50 static void count_handler(struct tevent_context *ev_ctx, struct signal_event *te,
51                           int signum, int count, void *info, void *private_data)
52 {
53         int *countp = (int *)private_data;
54         (*countp) += count;
55 }
56
57 static bool test_event_context(struct torture_context *test,
58                                const void *test_data)
59 {
60         struct tevent_context *ev_ctx;
61         int fd[2] = { -1, -1 };
62         const char *backend = (const char *)test_data;
63         int alarm_count=0, info_count=0;
64         struct tevent_fd *fde;
65         struct signal_event *se1, *se2, *se3;
66         int finished=0;
67         struct timeval t;
68         char c = 0;
69
70         ev_ctx = event_context_init_byname(test, backend);
71         if (ev_ctx == NULL) {
72                 torture_comment(test, "event backend '%s' not supported\n", backend);
73                 return true;
74         }
75
76         torture_comment(test, "Testing event backend '%s'\n", backend);
77
78         /* reset globals */
79         fde_count = 0;
80
81         /* create a pipe */
82         pipe(fd);
83
84         fde = event_add_fd(ev_ctx, ev_ctx, fd[0], EVENT_FD_READ,
85                            fde_handler, fd);
86         tevent_fd_set_auto_close(fde);
87
88         event_add_timed(ev_ctx, ev_ctx, timeval_current_ofs(2,0), 
89                         finished_handler, &finished);
90
91         se1 = event_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
92         se2 = event_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
93 #ifdef SA_SIGINFO
94         se3 = event_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
95 #endif
96
97         write(fd[1], &c, 1);
98
99         t = timeval_current();
100         while (!finished) {
101                 errno = 0;
102                 if (event_loop_once(ev_ctx) == -1) {
103                         talloc_free(ev_ctx);
104                         torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno)));
105                 }
106         }
107
108         talloc_free(fde);
109         close(fd[1]);
110
111         while (alarm_count < fde_count+1) {
112                 if (event_loop_once(ev_ctx) == -1) {
113                         break;
114                 }
115         }
116
117         torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
118
119         talloc_free(se1);
120
121         torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
122
123 #ifdef SA_SIGINFO
124         talloc_free(se3);
125         torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
126 #endif
127
128         talloc_free(ev_ctx);
129
130         return true;
131 }
132
133 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
134 {
135         struct torture_suite *suite = torture_suite_create(mem_ctx, "EVENT");
136         const char **list = event_backend_list(suite);
137         int i;
138
139         for (i=0;list && list[i];i++) {
140                 torture_suite_add_simple_tcase_const(suite, list[i],
141                                                test_event_context,
142                                                (const void *)list[i]);
143         }
144
145         return suite;
146 }