Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * testing of some tevent_req aspects
5 : *
6 : * Copyright (C) Volker Lendecke 2018
7 : *
8 : * ** NOTE! The following LGPL license applies to the tevent
9 : * ** library. This does NOT imply that all of Samba is released
10 : * ** under the LGPL
11 : *
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.
16 : *
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.
21 : *
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/>.
24 : */
25 :
26 : #include "includes.h"
27 : #include "tevent.h"
28 : #include "torture/torture.h"
29 : #include "torture/local/proto.h"
30 : #include "lib/util/tevent_unix.h"
31 : #include "lib/util/tevent_req_profile.h"
32 : #include "lib/util/time_basic.h"
33 :
34 : struct tevent_req_create_state {
35 : uint8_t val;
36 : };
37 :
38 1 : static bool test_tevent_req_create(struct torture_context *tctx,
39 : const void *test_data)
40 : {
41 1 : struct tevent_req *req;
42 1 : struct tevent_req_create_state *state;
43 :
44 1 : req = tevent_req_create(tctx, &state,
45 : struct tevent_req_create_state);
46 1 : torture_assert_not_null(tctx, req, "tevent_req_create failed\n");
47 1 : torture_assert_int_equal(tctx, state->val, 0, "state not initialized\n");
48 :
49 1 : TALLOC_FREE(req);
50 :
51 1 : return true;
52 : }
53 :
54 : struct profile1_state {
55 : uint8_t dummy;
56 : };
57 :
58 1 : static bool test_tevent_req_profile1(struct torture_context *tctx,
59 : const void *test_data)
60 : {
61 1 : struct tevent_req *req;
62 1 : struct profile1_state *state;
63 1 : const struct tevent_req_profile *p1;
64 1 : struct tevent_req_profile *p2;
65 1 : struct timeval start, stop;
66 1 : bool ok;
67 1 : int cmp;
68 :
69 1 : req = tevent_req_create(tctx, &state, struct profile1_state);
70 1 : torture_assert_not_null(tctx, req, "tevent_req_create failed\n");
71 :
72 1 : p1 = tevent_req_get_profile(req);
73 1 : torture_assert(tctx, p1 == NULL, "profile not initialized to NULL\n");
74 :
75 1 : ok = tevent_req_set_profile(req);
76 1 : torture_assert(tctx, ok, "set_profile failed\n");
77 :
78 1 : tevent_req_done(req);
79 :
80 1 : p2 = tevent_req_move_profile(req, tctx);
81 1 : torture_assert_not_null(tctx, p2, "get_profile failed\n");
82 :
83 : /* Demonstrate sure "p2" outlives req */
84 1 : TALLOC_FREE(req);
85 :
86 1 : tevent_req_profile_get_start(p2, NULL, &start);
87 1 : tevent_req_profile_get_stop(p2, NULL, &stop);
88 :
89 1 : cmp = tevent_timeval_compare(&start, &stop);
90 1 : torture_assert(tctx, cmp <= 0, "stop before start\n");
91 :
92 1 : TALLOC_FREE(p2);
93 :
94 1 : return true;
95 : }
96 :
97 : struct profile2_state {
98 : uint8_t dummy;
99 : };
100 :
101 : static void profile2_done(struct tevent_req *subreq);
102 :
103 1 : static struct tevent_req *profile2_send(TALLOC_CTX *mem_ctx,
104 : struct tevent_context *ev)
105 : {
106 1 : struct tevent_req *req, *subreq;
107 1 : struct profile2_state *state;
108 1 : bool ok;
109 :
110 1 : req = tevent_req_create(mem_ctx, &state, struct profile2_state);
111 1 : if (req == NULL) {
112 0 : return NULL;
113 : }
114 :
115 1 : ok = tevent_req_set_profile(req);
116 1 : if (!ok) {
117 0 : return tevent_req_post(req, ev);
118 : }
119 :
120 1 : subreq = tevent_wakeup_send(
121 : state,
122 : ev,
123 : tevent_timeval_current_ofs(0, 1));
124 1 : if (tevent_req_nomem(subreq, req)) {
125 0 : return tevent_req_post(req, ev);
126 : }
127 1 : tevent_req_set_callback(subreq, profile2_done, req);
128 :
129 1 : return req;
130 : }
131 :
132 1 : static void profile2_done(struct tevent_req *subreq)
133 : {
134 1 : struct tevent_req *req = tevent_req_callback_data(
135 : subreq, struct tevent_req);
136 1 : bool ok;
137 :
138 1 : ok = tevent_wakeup_recv(subreq);
139 1 : if (!ok) {
140 0 : tevent_req_oom(req);
141 0 : return;
142 : }
143 1 : tevent_req_done(req);
144 : }
145 :
146 1 : static int profile2_recv(struct tevent_req *req,
147 : TALLOC_CTX *mem_ctx,
148 : struct tevent_req_profile **profile)
149 : {
150 1 : int err;
151 :
152 1 : if (tevent_req_is_unix_error(req, &err)) {
153 0 : return err;
154 : }
155 :
156 1 : *profile = tevent_req_move_profile(req, mem_ctx);
157 :
158 1 : return 0;
159 : }
160 :
161 1 : static bool test_tevent_req_profile2(struct torture_context *tctx,
162 : const void *test_data)
163 : {
164 1 : struct tevent_context *ev;
165 1 : struct tevent_req *req;
166 1 : struct tevent_req_profile *p1 = NULL;
167 1 : struct tevent_req_profile *p2 = NULL;
168 1 : const char *str1, *str2;
169 1 : struct timeval tv1, tv2;
170 1 : pid_t pid1, pid2;
171 1 : enum tevent_req_state state1, state2;
172 1 : uint64_t err1, err2;
173 1 : char *printstring;
174 1 : ssize_t pack_len;
175 1 : int err;
176 1 : bool ok;
177 :
178 1 : ev = samba_tevent_context_init(tctx);
179 1 : torture_assert_not_null(tctx, ev, "samba_tevent_context_init failed\n");
180 :
181 1 : req = profile2_send(tctx, ev);
182 1 : torture_assert_not_null(tctx, req, "profile2_send failed\n");
183 :
184 1 : ok = tevent_req_poll_unix(req, ev, &err);
185 1 : torture_assert(tctx, ok, "tevent_req_poll_unix failed\n");
186 :
187 1 : err = profile2_recv(req, tctx, &p1);
188 1 : torture_assert_int_equal(tctx, err, 0, "profile2_recv failed\n");
189 :
190 1 : TALLOC_FREE(req);
191 1 : TALLOC_FREE(ev);
192 :
193 1 : printstring = tevent_req_profile_string(tctx, p1, 0, UINT_MAX);
194 1 : torture_assert_not_null(
195 : tctx,
196 : printstring,
197 : "tevent_req_profile_string failed\n");
198 1 : printf("%s\n", printstring);
199 :
200 1 : pack_len = tevent_req_profile_pack(p1, NULL, 0);
201 1 : torture_assert(tctx, pack_len>0, "profile_pack failed\n");
202 :
203 1 : {
204 1 : uint8_t buf[pack_len];
205 1 : ssize_t unpack_len;
206 :
207 1 : tevent_req_profile_pack(p1, buf, sizeof(buf));
208 1 : dump_data(10, buf, sizeof(buf));
209 :
210 1 : unpack_len = tevent_req_profile_unpack(
211 : buf,
212 : pack_len,
213 : tctx,
214 : &p2);
215 1 : torture_assert_int_equal(tctx,
216 : pack_len,
217 : unpack_len,
218 : "profile_unpack failed\n");
219 : }
220 :
221 1 : printstring = tevent_req_profile_string(tctx, p2, 0, UINT_MAX);
222 1 : torture_assert_not_null(
223 : tctx,
224 : printstring,
225 : "tevent_req_profile_string failed\n");
226 1 : printf("%s\n", printstring);
227 :
228 1 : tevent_req_profile_get_name(p1, &str1);
229 1 : tevent_req_profile_get_name(p2, &str2);
230 1 : torture_assert_str_equal(tctx, str1, str2, "names differ\n");
231 :
232 1 : tevent_req_profile_get_start(p1, &str1, &tv1);
233 1 : tevent_req_profile_get_start(p2, &str2, &tv2);
234 1 : torture_assert_str_equal(tctx, str1, str2, "start strings differ\n");
235 1 : torture_assert(tctx,
236 : tevent_timeval_compare(&tv1, &tv2) == 0,
237 : "start times differ\n");
238 :
239 1 : tevent_req_profile_get_stop(p1, &str1, &tv1);
240 1 : tevent_req_profile_get_stop(p2, &str2, &tv2);
241 1 : torture_assert_str_equal(tctx, str1, str2, "stop strings differ\n");
242 1 : torture_assert(tctx,
243 : tevent_timeval_compare(&tv1, &tv2) == 0,
244 : "stop times differ\n");
245 :
246 1 : tevent_req_profile_get_status(p1, &pid1, &state1, &err1);
247 1 : tevent_req_profile_get_status(p2, &pid2, &state2, &err2);
248 1 : torture_assert_int_equal(tctx, pid1, pid2, "pids differ\n");
249 1 : torture_assert_int_equal(tctx, state1, state2, "states differ\n");
250 1 : torture_assert_int_equal(tctx, err1, err2, "user errors differ\n");
251 :
252 1 : str1 = tevent_req_profile_string(p1, p1, 0, UINT_MAX);
253 1 : torture_assert_not_null(tctx, str1, "profile_string failed\n");
254 1 : str2 = tevent_req_profile_string(p2, p2, 0, UINT_MAX);
255 1 : torture_assert_not_null(tctx, str2, "profile_string failed\n");
256 :
257 1 : torture_assert_str_equal(tctx, str1, str2, "result strings differ\n");
258 :
259 1 : TALLOC_FREE(p1);
260 1 : TALLOC_FREE(p2);
261 :
262 0 : return true;
263 : }
264 :
265 2354 : struct torture_suite *torture_local_tevent_req(TALLOC_CTX *mem_ctx)
266 : {
267 125 : struct torture_suite *suite;
268 :
269 2354 : suite = torture_suite_create(mem_ctx, "tevent_req");
270 :
271 2354 : torture_suite_add_simple_tcase_const(
272 : suite,
273 : "create",
274 : test_tevent_req_create,
275 : NULL);
276 2354 : torture_suite_add_simple_tcase_const(
277 : suite,
278 : "profile1",
279 : test_tevent_req_profile1,
280 : NULL);
281 2354 : torture_suite_add_simple_tcase_const(
282 : suite,
283 : "profile2",
284 : test_tevent_req_profile2,
285 : NULL);
286 :
287 2354 : return suite;
288 : }
|