0bb3128cd887e5382dbaaee62276a6b3fa661608
[obnox/samba/samba-obnox.git] / source3 / torture / test_messaging_read.c
1 /*
2    Unix SMB/CIFS implementation.
3    Test for a messaging_read bug
4    Copyright (C) Volker Lendecke 2014
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "torture/proto.h"
22 #include "lib/util/tevent_unix.h"
23 #include "messages.h"
24
25 struct msg_count_state {
26         struct tevent_context *ev;
27         struct messaging_context *msg_ctx;
28         uint32_t msg_type;
29         unsigned *count;
30 };
31
32 static void msg_count_done(struct tevent_req *subreq);
33
34 static struct tevent_req *msg_count_send(TALLOC_CTX *mem_ctx,
35                                          struct tevent_context *ev,
36                                          struct messaging_context *msg_ctx,
37                                          uint32_t msg_type,
38                                          unsigned *count)
39 {
40         struct tevent_req *req, *subreq;
41         struct msg_count_state *state;
42
43         req = tevent_req_create(mem_ctx, &state, struct msg_count_state);
44         if (req == NULL) {
45                 return NULL;
46         }
47         state->ev = ev;
48         state->msg_ctx = msg_ctx;
49         state->msg_type = msg_type;
50         state->count = count;
51
52         subreq = messaging_read_send(state, state->ev, state->msg_ctx,
53                                      state->msg_type);
54         if (tevent_req_nomem(subreq, req)) {
55                 return tevent_req_post(req, ev);
56         }
57         tevent_req_set_callback(subreq, msg_count_done, req);
58         return req;
59 }
60
61 static void msg_count_done(struct tevent_req *subreq)
62 {
63         struct tevent_req *req = tevent_req_callback_data(
64                 subreq, struct tevent_req);
65         struct msg_count_state *state = tevent_req_data(
66                 req, struct msg_count_state);
67         int ret;
68
69         ret = messaging_read_recv(subreq, NULL, NULL);
70         TALLOC_FREE(subreq);
71         if (tevent_req_error(req, ret)) {
72                 return;
73         }
74         *state->count += 1;
75
76         subreq = messaging_read_send(state, state->ev, state->msg_ctx,
77                                      state->msg_type);
78         if (tevent_req_nomem(subreq, req)) {
79                 return;
80         }
81         tevent_req_set_callback(subreq, msg_count_done, req);
82 }
83
84 bool run_messaging_read1(int dummy)
85 {
86         struct tevent_context *ev = NULL;
87         struct messaging_context *msg_ctx = NULL;
88         struct tevent_req *req1 = NULL;
89         unsigned count1 = 0;
90         struct tevent_req *req2 = NULL;
91         unsigned count2 = 0;
92         NTSTATUS status;
93         bool retval = false;
94         int i;
95
96         ev = samba_tevent_context_init(talloc_tos());
97         if (ev == NULL) {
98                 fprintf(stderr, "tevent_context_init failed\n");
99                 goto fail;
100         }
101         msg_ctx = messaging_init(ev, ev);
102         if (msg_ctx == NULL) {
103                 fprintf(stderr, "messaging_init failed\n");
104                 goto fail;
105         }
106
107         req1 = msg_count_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &count1);
108         if (req1 == NULL) {
109                 fprintf(stderr, "msg_count_send failed\n");
110                 goto fail;
111         }
112         req2 = msg_count_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &count2);
113         if (req1 == NULL) {
114                 fprintf(stderr, "msg_count_send failed\n");
115                 goto fail;
116         }
117         status = messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
118                                     MSG_SMB_NOTIFY, NULL, 0);
119         if (!NT_STATUS_IS_OK(status)) {
120                 fprintf(stderr, "messaging_send_buf failed: %s\n",
121                         nt_errstr(status));
122                 goto fail;
123         }
124
125         for (i=0; i<2; i++) {
126                 if (tevent_loop_once(ev) != 0) {
127                         fprintf(stderr, "tevent_loop_once failed\n");
128                         goto fail;
129                 }
130         }
131
132         printf("%u/%u\n", count1, count2);
133
134         if ((count1 != 1) || (count2 != 1)){
135                 fprintf(stderr, "Got %u/%u msgs, expected 1 each\n",
136                         count1, count2);
137                 goto fail;
138         }
139
140         retval = true;
141 fail:
142         TALLOC_FREE(req1);
143         TALLOC_FREE(req2);
144         TALLOC_FREE(msg_ctx);
145         TALLOC_FREE(ev);
146         return retval;
147 }
148
149 struct msg_free_state {
150         struct tevent_req **to_free;
151 };
152
153 static void msg_free_done(struct tevent_req *subreq);
154
155 static struct tevent_req *msg_free_send(TALLOC_CTX *mem_ctx,
156                                         struct tevent_context *ev,
157                                         struct messaging_context *msg_ctx,
158                                         uint32_t msg_type,
159                                         struct tevent_req **to_free)
160 {
161         struct tevent_req *req, *subreq;
162         struct msg_free_state *state;
163
164         req = tevent_req_create(mem_ctx, &state, struct msg_free_state);
165         if (req == NULL) {
166                 return NULL;
167         }
168         state->to_free = to_free;
169
170         subreq = messaging_read_send(state, ev, msg_ctx, msg_type);
171         if (tevent_req_nomem(subreq, req)) {
172                 return tevent_req_post(req, ev);
173         }
174         tevent_req_set_callback(subreq, msg_free_done, req);
175         return req;
176 }
177
178 static void msg_free_done(struct tevent_req *subreq)
179 {
180         struct tevent_req *req = tevent_req_callback_data(
181                 subreq, struct tevent_req);
182         struct msg_free_state *state = tevent_req_data(
183                 req, struct msg_free_state);
184         int ret;
185
186         ret = messaging_read_recv(subreq, NULL, NULL);
187         TALLOC_FREE(subreq);
188         if (tevent_req_error(req, ret)) {
189                 return;
190         }
191         TALLOC_FREE(*state->to_free);
192         tevent_req_done(req);
193 }
194
195 bool run_messaging_read2(int dummy)
196 {
197         struct tevent_context *ev = NULL;
198         struct messaging_context *msg_ctx = NULL;
199         struct tevent_req *req1 = NULL;
200         struct tevent_req *req2 = NULL;
201         unsigned count = 0;
202         NTSTATUS status;
203         bool retval = false;
204
205         ev = samba_tevent_context_init(talloc_tos());
206         if (ev == NULL) {
207                 fprintf(stderr, "tevent_context_init failed\n");
208                 goto fail;
209         }
210         msg_ctx = messaging_init(ev, ev);
211         if (msg_ctx == NULL) {
212                 fprintf(stderr, "messaging_init failed\n");
213                 goto fail;
214         }
215
216         req1 = msg_free_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &req2);
217         if (req1 == NULL) {
218                 fprintf(stderr, "msg_count_send failed\n");
219                 goto fail;
220         }
221         req2 = msg_count_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &count);
222         if (req1 == NULL) {
223                 fprintf(stderr, "msg_count_send failed\n");
224                 goto fail;
225         }
226         status = messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
227                                     MSG_SMB_NOTIFY, NULL, 0);
228         if (!NT_STATUS_IS_OK(status)) {
229                 fprintf(stderr, "messaging_send_buf failed: %s\n",
230                         nt_errstr(status));
231                 goto fail;
232         }
233
234         if (!tevent_req_poll(req1, ev) != 0) {
235                 fprintf(stderr, "tevent_req_poll failed\n");
236                 goto fail;
237         }
238
239         if (count != 0) {
240                 fprintf(stderr, "Got %u msgs, expected none\n", count);
241                 goto fail;
242         }
243
244         retval = true;
245 fail:
246         TALLOC_FREE(req1);
247         TALLOC_FREE(msg_ctx);
248         TALLOC_FREE(ev);
249         return retval;
250 }