1a6f317ca69fa8859cb4bd8a1ff803612a57ea83
[tprouty/samba.git] / source4 / torture / local / event.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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "lib/events/events.h"
25 #include "system/filesys.h"
26 #include "torture/torture.h"
27
28 static int fde_count;
29
30 static void fde_handler(struct event_context *ev_ctx, struct fd_event *f, 
31                         uint16_t flags, void *private)
32 {
33         int *fd = private;
34         char c;
35 #ifdef SA_SIGINFO
36         kill(getpid(), SIGUSR1);
37 #endif
38         kill(getpid(), SIGALRM);
39         read(fd[0], &c, 1);
40         write(fd[1], &c, 1);
41         fde_count++;
42 }
43
44 static void finished_handler(struct event_context *ev_ctx, struct timed_event *te,
45                              struct timeval tval, void *private)
46 {
47         int *finished = private;
48         (*finished) = 1;
49 }
50
51 static void count_handler(struct event_context *ev_ctx, struct signal_event *te,
52                           int signum, int count, void *info, void *private)
53 {
54         int *countp = private;
55         (*countp) += count;
56 }
57
58 static bool test_event_context(struct torture_context *test,
59                                const void *test_data)
60 {
61         struct event_context *ev_ctx;
62         int fd[2] = { -1, -1 };
63         const char *backend = (const char *)test_data;
64         int alarm_count=0, info_count=0;
65         struct fd_event *fde;
66         struct signal_event *se1, *se2, *se3;
67         int finished=0;
68         struct timeval t;
69         char c = 0;
70
71         ev_ctx = event_context_init_byname(test, backend);
72         if (ev_ctx == NULL) {
73                 torture_comment(test, "event backend '%s' not supported\n", backend);
74                 return true;
75         }
76
77         torture_comment(test, "Testing event backend '%s'\n", backend);
78
79         /* reset globals */
80         fde_count = 0;
81
82         /* create a pipe */
83         pipe(fd);
84
85         fde = event_add_fd(ev_ctx, ev_ctx, fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE, 
86                            fde_handler, fd);
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                 if (event_loop_once(ev_ctx) == -1) {
102                         talloc_free(ev_ctx);
103                         torture_fail(test, "Failed event loop\n");
104                 }
105         }
106
107         talloc_free(fde);
108         close(fd[1]);
109
110         while (alarm_count < fde_count+1) {
111                 if (event_loop_once(ev_ctx) == -1) {
112                         break;
113                 }
114         }
115
116         torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t));
117
118         talloc_free(se1);
119
120         torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
121
122 #ifdef SA_SIGINFO
123         talloc_free(se3);
124         torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
125 #endif
126
127         talloc_free(ev_ctx);
128
129         return true;
130 }
131
132 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
133 {
134         struct torture_suite *suite = torture_suite_create(mem_ctx, "EVENT");
135         const char **list = event_backend_list(suite);
136         int i;
137
138         for (i=0;list && list[i];i++) {
139                 torture_suite_add_simple_tcase(suite, list[i],
140                                                test_event_context,
141                                                (const void *)list[i]);
142         }
143
144         return suite;
145 }