Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <talloc.h>
22 : #include <tevent.h>
23 : #include <errno.h>
24 : #include <popt.h>
25 : #include <time.h>
26 :
27 : #include "providers/dp_backend.h"
28 : #include "providers/dp_ptask_private.h"
29 : #include "providers/dp_ptask.h"
30 : #include "tests/cmocka/common_mock.h"
31 : #include "tests/cmocka/common_mock_be.h"
32 : #include "tests/common.h"
33 :
34 : #define DELAY 2
35 : #define PERIOD 1
36 :
37 : #define new_test(test) \
38 : cmocka_unit_test_setup_teardown(test_ ## test, test_setup, test_teardown)
39 :
40 : struct test_ctx {
41 : struct sss_test_ctx *tctx;
42 : struct be_ctx *be_ctx;
43 :
44 : time_t when;
45 : bool done;
46 :
47 : bool add_online_cb_called;
48 : bool add_offline_cb_called;
49 : };
50 :
51 : #define mark_online(test_ctx) do { \
52 : test_ctx->be_ctx->offstat.went_offline = 0; \
53 : test_ctx->be_ctx->offstat.offline = false; \
54 : } while (0)
55 :
56 : #define mark_offline(test_ctx) do { \
57 : test_ctx->be_ctx->offstat.went_offline = get_current_time(); \
58 : test_ctx->be_ctx->offstat.offline = true; \
59 : } while (0)
60 :
61 : /* Since both test_ctx->done and ptask->req is marked as finished already
62 : * in the sync _send function before a new execution is scheduled we need to
63 : * rely on the fact that ptask->req is set to zero when a new timer is
64 : * created. This way we guarantee that the condition is true only when
65 : * the ptask is executed and a new one is scheduled. */
66 : #define is_sync_ptask_finished(test_ctx, ptask) \
67 : (test_ctx->done && ptask->req == NULL)
68 :
69 41 : static time_t get_current_time(void)
70 : {
71 : struct timeval tv;
72 : int ret;
73 :
74 41 : ret = gettimeofday(&tv, NULL);
75 41 : assert_int_equal(0, ret);
76 41 : return tv.tv_sec;
77 : }
78 :
79 : /* Mock few backend functions so we don't have to bring the whole
80 : * data provider into this test. */
81 :
82 19 : bool be_is_offline(struct be_ctx *ctx)
83 : {
84 19 : return ctx->offstat.offline;
85 : }
86 :
87 1 : int be_add_online_cb(TALLOC_CTX *mem_ctx,
88 : struct be_ctx *ctx,
89 : be_callback_t cb,
90 : void *pvt,
91 : struct be_cb **online_cb)
92 : {
93 1 : struct test_ctx *test_ctx = NULL;
94 :
95 1 : test_ctx = sss_mock_ptr_type(struct test_ctx *);
96 1 : test_ctx->add_online_cb_called = true;
97 :
98 1 : return ERR_OK;
99 : }
100 :
101 1 : int be_add_offline_cb(TALLOC_CTX *mem_ctx,
102 : struct be_ctx *ctx,
103 : be_callback_t cb,
104 : void *pvt,
105 : struct be_cb **offline_cb)
106 : {
107 1 : struct test_ctx *test_ctx = NULL;
108 :
109 1 : test_ctx = sss_mock_ptr_type(struct test_ctx *);
110 1 : test_ctx->add_offline_cb_called = true;
111 :
112 1 : return ERR_OK;
113 : }
114 :
115 : struct test_be_ptask_state {
116 : struct test_ctx *test_ctx;
117 : };
118 :
119 10 : struct tevent_req * test_be_ptask_send(TALLOC_CTX *mem_ctx,
120 : struct tevent_context *ev,
121 : struct be_ctx *be_ctx,
122 : struct be_ptask *be_ptask,
123 : void *pvt)
124 : {
125 10 : struct test_be_ptask_state *state = NULL;
126 10 : struct test_ctx *test_ctx = NULL;
127 10 : struct tevent_req *req = NULL;
128 :
129 10 : assert_non_null(ev);
130 10 : assert_non_null(be_ctx);
131 10 : assert_non_null(be_ptask);
132 10 : assert_non_null(pvt);
133 :
134 10 : test_ctx = talloc_get_type(pvt, struct test_ctx);
135 10 : assert_non_null(test_ctx);
136 :
137 10 : test_ctx->when = get_current_time();
138 :
139 10 : req = tevent_req_create(mem_ctx, &state, struct test_be_ptask_state);
140 10 : assert_non_null(req);
141 :
142 10 : state->test_ctx = test_ctx;
143 :
144 10 : tevent_req_done(req);
145 10 : tevent_req_post(req, ev);
146 10 : return req;
147 : }
148 :
149 1 : struct tevent_req * test_be_ptask_null_send(TALLOC_CTX *mem_ctx,
150 : struct tevent_context *ev,
151 : struct be_ctx *be_ctx,
152 : struct be_ptask *be_ptask,
153 : void *pvt)
154 : {
155 1 : struct test_ctx *test_ctx = NULL;
156 1 : assert_non_null(ev);
157 1 : assert_non_null(be_ctx);
158 1 : assert_non_null(be_ptask);
159 1 : assert_non_null(pvt);
160 :
161 1 : test_ctx = talloc_get_type(pvt, struct test_ctx);
162 1 : assert_non_null(test_ctx);
163 :
164 1 : test_ctx->when = get_current_time();
165 1 : test_ctx->done = true;
166 :
167 1 : return NULL;
168 : }
169 :
170 1 : struct tevent_req * test_be_ptask_timeout_send(TALLOC_CTX *mem_ctx,
171 : struct tevent_context *ev,
172 : struct be_ctx *be_ctx,
173 : struct be_ptask *be_ptask,
174 : void *pvt)
175 : {
176 1 : struct test_be_ptask_state *state = NULL;
177 1 : struct test_ctx *test_ctx = NULL;
178 1 : struct tevent_req *req = NULL;
179 :
180 1 : assert_non_null(ev);
181 1 : assert_non_null(be_ctx);
182 1 : assert_non_null(be_ptask);
183 1 : assert_non_null(pvt);
184 :
185 1 : test_ctx = talloc_get_type(pvt, struct test_ctx);
186 1 : assert_non_null(test_ctx);
187 :
188 1 : test_ctx->when = get_current_time();
189 :
190 1 : req = tevent_req_create(mem_ctx, &state, struct test_be_ptask_state);
191 1 : assert_non_null(req);
192 :
193 1 : state->test_ctx = test_ctx;
194 :
195 : /* we won't finish the request */
196 :
197 1 : return req;
198 : }
199 :
200 9 : errno_t test_be_ptask_recv(struct tevent_req *req)
201 : {
202 9 : struct test_be_ptask_state *state = NULL;
203 :
204 9 : state = tevent_req_data(req, struct test_be_ptask_state);
205 9 : assert_non_null(state);
206 :
207 9 : state->test_ctx->done = true;
208 :
209 9 : TEVENT_REQ_RETURN_ON_ERROR(req);
210 :
211 9 : return ERR_OK;
212 : }
213 :
214 1 : errno_t test_be_ptask_error_recv(struct tevent_req *req)
215 : {
216 1 : struct test_be_ptask_state *state = NULL;
217 :
218 1 : state = tevent_req_data(req, struct test_be_ptask_state);
219 1 : assert_non_null(state);
220 :
221 1 : state->test_ctx->done = true;
222 :
223 1 : return ERR_INTERNAL;
224 : }
225 :
226 2 : errno_t test_be_ptask_sync(TALLOC_CTX *mem_ctx,
227 : struct tevent_context *ev,
228 : struct be_ctx *be_ctx,
229 : struct be_ptask *be_ptask,
230 : void *pvt)
231 : {
232 2 : struct test_ctx *test_ctx = NULL;
233 :
234 2 : assert_non_null(ev);
235 2 : assert_non_null(be_ctx);
236 2 : assert_non_null(be_ptask);
237 2 : assert_non_null(pvt);
238 :
239 2 : test_ctx = talloc_get_type(pvt, struct test_ctx);
240 2 : assert_non_null(test_ctx);
241 :
242 2 : test_ctx->when = get_current_time();
243 2 : test_ctx->done = true;
244 :
245 2 : return ERR_OK;
246 : }
247 :
248 3 : errno_t test_be_ptask_sync_error(TALLOC_CTX *mem_ctx,
249 : struct tevent_context *ev,
250 : struct be_ctx *be_ctx,
251 : struct be_ptask *be_ptask,
252 : void *pvt)
253 : {
254 3 : struct test_ctx *test_ctx = NULL;
255 :
256 3 : assert_non_null(ev);
257 3 : assert_non_null(be_ctx);
258 3 : assert_non_null(be_ptask);
259 3 : assert_non_null(pvt);
260 :
261 3 : test_ctx = talloc_get_type(pvt, struct test_ctx);
262 3 : assert_non_null(test_ctx);
263 :
264 3 : test_ctx->when = get_current_time();
265 3 : test_ctx->done = true;
266 :
267 3 : return ERR_INTERNAL;
268 : }
269 :
270 23 : static int test_setup(void **state)
271 : {
272 23 : struct test_ctx *test_ctx = NULL;
273 :
274 23 : assert_true(leak_check_setup());
275 :
276 23 : test_ctx = talloc_zero(global_talloc_context, struct test_ctx);
277 23 : assert_non_null(test_ctx);
278 :
279 23 : test_ctx->tctx = create_ev_test_ctx(test_ctx);
280 23 : assert_non_null(test_ctx->tctx);
281 :
282 23 : test_ctx->be_ctx = mock_be_ctx(test_ctx, test_ctx->tctx);
283 23 : assert_non_null(test_ctx->be_ctx);
284 :
285 23 : test_ctx->be_ctx->ev = tevent_context_init(test_ctx->be_ctx);
286 23 : assert_non_null(test_ctx->be_ctx->ev);
287 :
288 23 : *state = test_ctx;
289 23 : return 0;
290 : }
291 :
292 23 : static int test_teardown(void **state)
293 : {
294 23 : talloc_zfree(*state);
295 23 : assert_true(leak_check_teardown());
296 23 : return 0;
297 : }
298 :
299 1 : void test_be_ptask_create_einval_be(void **state)
300 : {
301 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
302 1 : struct be_ptask *ptask = NULL;
303 : errno_t ret;
304 :
305 1 : ret = be_ptask_create(test_ctx, NULL, PERIOD, 0, 0, 0, 0,
306 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
307 : test_be_ptask_recv, NULL, "Test ptask", &ptask);
308 1 : assert_int_equal(ret, EINVAL);
309 1 : assert_null(ptask);
310 1 : }
311 :
312 1 : void test_be_ptask_create_einval_period(void **state)
313 : {
314 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
315 1 : struct be_ptask *ptask = NULL;
316 : errno_t ret;
317 :
318 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, 0, 0, 0, 0, 0,
319 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
320 : test_be_ptask_recv, NULL, "Test ptask", &ptask);
321 1 : assert_int_equal(ret, EINVAL);
322 1 : assert_null(ptask);
323 1 : }
324 :
325 1 : void test_be_ptask_create_einval_send(void **state)
326 : {
327 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
328 1 : struct be_ptask *ptask = NULL;
329 : errno_t ret;
330 :
331 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
332 : BE_PTASK_OFFLINE_SKIP, 0, NULL,
333 : test_be_ptask_recv, NULL, "Test ptask", &ptask);
334 1 : assert_int_equal(ret, EINVAL);
335 1 : assert_null(ptask);
336 1 : }
337 :
338 1 : void test_be_ptask_create_einval_recv(void **state)
339 : {
340 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
341 1 : struct be_ptask *ptask = NULL;
342 : errno_t ret;
343 :
344 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
345 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
346 : NULL, NULL, "Test ptask", &ptask);
347 1 : assert_int_equal(ret, EINVAL);
348 1 : assert_null(ptask);
349 1 : }
350 :
351 1 : void test_be_ptask_create_einval_name(void **state)
352 : {
353 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
354 1 : struct be_ptask *ptask = NULL;
355 : errno_t ret;
356 :
357 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
358 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
359 : test_be_ptask_recv, NULL, NULL, &ptask);
360 1 : assert_int_equal(ret, EINVAL);
361 1 : assert_null(ptask);
362 1 : }
363 :
364 1 : void test_be_ptask_create_no_delay(void **state)
365 : {
366 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
367 1 : struct be_ptask *ptask = NULL;
368 : time_t now;
369 : errno_t ret;
370 :
371 1 : now = get_current_time();
372 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
373 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
374 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
375 1 : assert_int_equal(ret, ERR_OK);
376 1 : assert_non_null(ptask);
377 1 : assert_non_null(ptask->timer);
378 :
379 4 : while (!test_ctx->done) {
380 2 : tevent_loop_once(test_ctx->be_ctx->ev);
381 : }
382 :
383 1 : assert_true(now <= ptask->last_execution);
384 1 : assert_true(now <= test_ctx->when);
385 1 : assert_true(ptask->last_execution <= test_ctx->when);
386 :
387 1 : be_ptask_destroy(&ptask);
388 1 : assert_null(ptask);
389 1 : }
390 :
391 1 : void test_be_ptask_create_first_delay(void **state)
392 : {
393 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
394 1 : struct be_ptask *ptask = NULL;
395 : time_t now;
396 : errno_t ret;
397 :
398 1 : now = get_current_time();
399 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, DELAY, 0, 0, 0,
400 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
401 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
402 1 : assert_int_equal(ret, ERR_OK);
403 1 : assert_non_null(ptask);
404 1 : assert_non_null(ptask->timer);
405 :
406 4 : while (!test_ctx->done) {
407 2 : tevent_loop_once(test_ctx->be_ctx->ev);
408 : }
409 :
410 1 : assert_true(now + DELAY <= ptask->last_execution);
411 1 : assert_true(now + DELAY <= test_ctx->when);
412 1 : assert_true(ptask->last_execution <= test_ctx->when);
413 :
414 1 : be_ptask_destroy(&ptask);
415 1 : assert_null(ptask);
416 1 : }
417 :
418 1 : void test_be_ptask_disable(void **state)
419 : {
420 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
421 1 : struct be_ptask *ptask = NULL;
422 : errno_t ret;
423 :
424 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
425 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
426 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
427 1 : assert_int_equal(ret, ERR_OK);
428 1 : assert_non_null(ptask);
429 1 : assert_non_null(ptask->timer);
430 :
431 1 : be_ptask_disable(ptask);
432 :
433 1 : assert_null(ptask->timer);
434 1 : assert_false(ptask->enabled);
435 :
436 1 : be_ptask_destroy(&ptask);
437 1 : assert_null(ptask);
438 1 : }
439 :
440 1 : void test_be_ptask_enable(void **state)
441 : {
442 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
443 1 : struct be_ptask *ptask = NULL;
444 : time_t now;
445 : errno_t ret;
446 :
447 1 : now = get_current_time();
448 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
449 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
450 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
451 1 : assert_int_equal(ret, ERR_OK);
452 1 : assert_non_null(ptask);
453 1 : assert_non_null(ptask->timer);
454 :
455 1 : be_ptask_disable(ptask);
456 :
457 1 : now = get_current_time();
458 1 : be_ptask_enable(ptask);
459 1 : assert_non_null(ptask->timer);
460 :
461 4 : while (!test_ctx->done) {
462 2 : tevent_loop_once(test_ctx->be_ctx->ev);
463 : }
464 :
465 1 : assert_true(now <= ptask->last_execution);
466 1 : assert_true(now <= test_ctx->when);
467 1 : assert_true(ptask->last_execution <= test_ctx->when);
468 :
469 1 : be_ptask_destroy(&ptask);
470 1 : assert_null(ptask);
471 1 : }
472 :
473 1 : void test_be_ptask_enable_delay(void **state)
474 : {
475 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
476 1 : struct be_ptask *ptask = NULL;
477 : time_t now;
478 : errno_t ret;
479 :
480 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, DELAY, 0, 0,
481 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
482 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
483 1 : assert_int_equal(ret, ERR_OK);
484 1 : assert_non_null(ptask);
485 1 : assert_non_null(ptask->timer);
486 :
487 4 : while (!test_ctx->done) {
488 2 : tevent_loop_once(test_ctx->be_ctx->ev);
489 : }
490 :
491 1 : be_ptask_disable(ptask);
492 1 : test_ctx->done = false;
493 1 : now = get_current_time();
494 1 : be_ptask_enable(ptask);
495 :
496 4 : while (!test_ctx->done) {
497 2 : tevent_loop_once(test_ctx->be_ctx->ev);
498 : }
499 :
500 1 : assert_true(now + DELAY <= ptask->last_execution);
501 1 : assert_true(now + DELAY <= test_ctx->when);
502 1 : assert_true(ptask->last_execution <= test_ctx->when);
503 :
504 1 : be_ptask_destroy(&ptask);
505 1 : assert_null(ptask);
506 1 : }
507 :
508 1 : void test_be_ptask_offline_skip(void **state)
509 : {
510 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
511 1 : struct be_ptask *ptask = NULL;
512 : time_t next_execution;
513 : time_t now;
514 : errno_t ret;
515 :
516 1 : mark_offline(test_ctx);
517 :
518 1 : now = get_current_time();
519 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
520 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
521 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
522 1 : assert_int_equal(ret, ERR_OK);
523 1 : assert_non_null(ptask);
524 1 : assert_non_null(ptask->timer);
525 :
526 1 : next_execution = ptask->next_execution;
527 1 : assert_true(now <= next_execution);
528 :
529 3 : while (ptask->next_execution == next_execution && !test_ctx->done) {
530 1 : tevent_loop_once(test_ctx->be_ctx->ev);
531 : }
532 :
533 1 : assert_true(next_execution + PERIOD <= ptask->next_execution);
534 1 : assert_true(ptask->enabled);
535 1 : assert_non_null(ptask->timer);
536 :
537 1 : be_ptask_destroy(&ptask);
538 1 : assert_null(ptask);
539 1 : }
540 :
541 1 : void test_be_ptask_offline_disable(void **state)
542 : {
543 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
544 1 : struct be_ptask *ptask = NULL;
545 : errno_t ret;
546 :
547 1 : mark_offline(test_ctx);
548 :
549 1 : will_return(be_add_online_cb, test_ctx);
550 1 : will_return(be_add_offline_cb, test_ctx);
551 :
552 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
553 : BE_PTASK_OFFLINE_DISABLE, 0, test_be_ptask_send,
554 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
555 1 : assert_int_equal(ret, ERR_OK);
556 1 : assert_non_null(ptask);
557 1 : assert_non_null(ptask->timer);
558 :
559 1 : assert_true(test_ctx->add_online_cb_called);
560 1 : assert_true(test_ctx->add_offline_cb_called);
561 :
562 3 : while (ptask->enabled && !test_ctx->done) {
563 1 : tevent_loop_once(test_ctx->be_ctx->ev);
564 : }
565 :
566 1 : assert_false(ptask->enabled);
567 1 : assert_false(test_ctx->done);
568 1 : assert_null(ptask->timer);
569 :
570 1 : be_ptask_destroy(&ptask);
571 1 : assert_null(ptask);
572 1 : }
573 :
574 1 : void test_be_ptask_offline_execute(void **state)
575 : {
576 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
577 1 : struct be_ptask *ptask = NULL;
578 : errno_t ret;
579 :
580 1 : mark_offline(test_ctx);
581 :
582 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
583 : BE_PTASK_OFFLINE_EXECUTE, 0, test_be_ptask_send,
584 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
585 1 : assert_int_equal(ret, ERR_OK);
586 1 : assert_non_null(ptask);
587 1 : assert_non_null(ptask->timer);
588 :
589 4 : while (!test_ctx->done) {
590 2 : tevent_loop_once(test_ctx->be_ctx->ev);
591 : }
592 :
593 1 : assert_true(ptask->enabled);
594 1 : assert_non_null(ptask->timer);
595 :
596 1 : be_ptask_destroy(&ptask);
597 1 : assert_null(ptask);
598 1 : }
599 :
600 1 : void test_be_ptask_reschedule_ok(void **state)
601 : {
602 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
603 1 : struct be_ptask *ptask = NULL;
604 : time_t next_execution;
605 : time_t now;
606 : errno_t ret;
607 :
608 1 : now = get_current_time();
609 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
610 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
611 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
612 1 : assert_int_equal(ret, ERR_OK);
613 1 : assert_non_null(ptask);
614 1 : assert_non_null(ptask->timer);
615 :
616 1 : next_execution = ptask->next_execution;
617 :
618 4 : while (!test_ctx->done) {
619 2 : tevent_loop_once(test_ctx->be_ctx->ev);
620 : }
621 :
622 1 : assert_true(now <= ptask->last_execution);
623 1 : assert_true(now <= test_ctx->when);
624 1 : assert_true(ptask->last_execution <= test_ctx->when);
625 :
626 1 : assert_true(next_execution + PERIOD <= ptask->next_execution);
627 1 : assert_non_null(ptask->timer);
628 :
629 1 : be_ptask_destroy(&ptask);
630 1 : assert_null(ptask);
631 1 : }
632 :
633 1 : void test_be_ptask_reschedule_null(void **state)
634 : {
635 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
636 1 : struct be_ptask *ptask = NULL;
637 1 : time_t now = 0;
638 : errno_t ret;
639 :
640 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
641 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_null_send,
642 : test_be_ptask_recv, test_ctx, "Test ptask",
643 : &ptask);
644 1 : assert_int_equal(ret, ERR_OK);
645 1 : assert_non_null(ptask);
646 1 : assert_non_null(ptask->timer);
647 :
648 3 : while (!test_ctx->done) {
649 1 : now = get_current_time();
650 1 : tevent_loop_once(test_ctx->be_ctx->ev);
651 : }
652 :
653 1 : assert_true(now + PERIOD <= ptask->next_execution);
654 1 : assert_non_null(ptask->timer);
655 :
656 1 : be_ptask_destroy(&ptask);
657 1 : assert_null(ptask);
658 1 : }
659 :
660 1 : void test_be_ptask_reschedule_error(void **state)
661 : {
662 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
663 1 : struct be_ptask *ptask = NULL;
664 1 : time_t now = 0;
665 : errno_t ret;
666 :
667 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
668 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
669 : test_be_ptask_error_recv, test_ctx, "Test ptask",
670 : &ptask);
671 1 : assert_int_equal(ret, ERR_OK);
672 1 : assert_non_null(ptask);
673 1 : assert_non_null(ptask->timer);
674 :
675 4 : while (!test_ctx->done) {
676 2 : now = get_current_time();
677 2 : tevent_loop_once(test_ctx->be_ctx->ev);
678 : }
679 :
680 1 : assert_true(now + PERIOD <= ptask->next_execution);
681 1 : assert_non_null(ptask->timer);
682 :
683 1 : be_ptask_destroy(&ptask);
684 1 : assert_null(ptask);
685 1 : }
686 :
687 1 : void test_be_ptask_reschedule_timeout(void **state)
688 : {
689 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
690 1 : struct be_ptask *ptask = NULL;
691 1 : time_t now = 0;
692 : errno_t ret;
693 :
694 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 1,
695 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_timeout_send,
696 : test_be_ptask_error_recv, test_ctx, "Test ptask",
697 : &ptask);
698 1 : assert_int_equal(ret, ERR_OK);
699 1 : assert_non_null(ptask);
700 1 : assert_non_null(ptask->timer);
701 :
702 : /* first iterate until the task is executed */
703 3 : while (!test_ctx->done && ptask->req == NULL) {
704 1 : tevent_loop_once(test_ctx->be_ctx->ev);
705 : }
706 :
707 : /* then iterate until the request is destroyed */
708 3 : while (!test_ctx->done && ptask->req != NULL) {
709 1 : now = get_current_time();
710 1 : tevent_loop_once(test_ctx->be_ctx->ev);
711 : }
712 :
713 1 : assert_false(test_ctx->done);
714 1 : assert_true(now + PERIOD <= ptask->next_execution);
715 1 : assert_non_null(ptask->timer);
716 :
717 1 : be_ptask_destroy(&ptask);
718 1 : assert_null(ptask);
719 1 : }
720 :
721 1 : void test_be_ptask_reschedule_backoff(void **state)
722 : {
723 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
724 1 : struct be_ptask *ptask = NULL;
725 : time_t next_execution;
726 : time_t now_first;
727 1 : time_t now_backoff = 0;
728 : errno_t ret;
729 :
730 1 : now_first = get_current_time();
731 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
732 : BE_PTASK_OFFLINE_SKIP, PERIOD*2, test_be_ptask_send,
733 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
734 1 : assert_int_equal(ret, ERR_OK);
735 1 : assert_non_null(ptask);
736 1 : assert_non_null(ptask->timer);
737 :
738 : /* first run */
739 1 : next_execution = ptask->next_execution;
740 :
741 4 : while (!test_ctx->done) {
742 : /* We need to acquire timestamp for the second test here, since this
743 : * is the closest value to the timestamp when the next event is
744 : * scheduled. */
745 2 : now_backoff = get_current_time();
746 2 : tevent_loop_once(test_ctx->be_ctx->ev);
747 : }
748 :
749 1 : assert_true(now_first <= ptask->last_execution);
750 1 : assert_true(now_first <= test_ctx->when);
751 1 : assert_true(ptask->last_execution <= test_ctx->when);
752 :
753 1 : assert_true(next_execution + PERIOD <= ptask->next_execution);
754 1 : assert_int_equal(PERIOD*2, ptask->period);
755 1 : assert_non_null(ptask->timer);
756 :
757 1 : test_ctx->done = false;
758 :
759 : /* second run */
760 1 : next_execution = ptask->next_execution;
761 :
762 4 : while (!test_ctx->done) {
763 2 : tevent_loop_once(test_ctx->be_ctx->ev);
764 : }
765 :
766 1 : assert_true(now_backoff + PERIOD <= ptask->last_execution);
767 1 : assert_true(now_backoff + PERIOD <= test_ctx->when);
768 1 : assert_true(ptask->last_execution <= test_ctx->when);
769 :
770 1 : assert_true(next_execution + PERIOD*2 <= ptask->next_execution);
771 1 : assert_int_equal(PERIOD*2, ptask->period);
772 1 : assert_non_null(ptask->timer);
773 :
774 1 : be_ptask_destroy(&ptask);
775 1 : assert_null(ptask);
776 1 : }
777 :
778 1 : void test_be_ptask_get_period(void **state)
779 : {
780 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
781 1 : struct be_ptask *ptask = NULL;
782 : time_t out_period;
783 : errno_t ret;
784 :
785 1 : ret = be_ptask_create(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
786 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_send,
787 : test_be_ptask_recv, test_ctx, "Test ptask", &ptask);
788 1 : assert_int_equal(ret, ERR_OK);
789 1 : assert_non_null(ptask);
790 :
791 1 : out_period = be_ptask_get_period(ptask);
792 1 : assert_true(PERIOD == out_period);
793 :
794 1 : be_ptask_destroy(&ptask);
795 1 : assert_null(ptask);
796 1 : }
797 :
798 1 : void test_be_ptask_create_sync(void **state)
799 : {
800 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
801 1 : struct be_ptask *ptask = NULL;
802 : time_t now;
803 : errno_t ret;
804 :
805 1 : now = get_current_time();
806 1 : ret = be_ptask_create_sync(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
807 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_sync,
808 : test_ctx, "Test ptask", &ptask);
809 1 : assert_int_equal(ret, ERR_OK);
810 1 : assert_non_null(ptask);
811 1 : assert_non_null(ptask->timer);
812 :
813 3 : while (!test_ctx->done) {
814 1 : tevent_loop_once(test_ctx->be_ctx->ev);
815 : }
816 :
817 1 : assert_true(now <= ptask->last_execution);
818 1 : assert_true(now <= test_ctx->when);
819 1 : assert_true(ptask->last_execution <= test_ctx->when);
820 :
821 1 : be_ptask_destroy(&ptask);
822 1 : assert_null(ptask);
823 1 : }
824 :
825 1 : void test_be_ptask_sync_reschedule_ok(void **state)
826 : {
827 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
828 1 : struct be_ptask *ptask = NULL;
829 : time_t next_execution;
830 : time_t now;
831 : errno_t ret;
832 :
833 1 : now = get_current_time();
834 1 : ret = be_ptask_create_sync(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
835 : BE_PTASK_OFFLINE_SKIP, 0, test_be_ptask_sync,
836 : test_ctx, "Test ptask", &ptask);
837 1 : assert_int_equal(ret, ERR_OK);
838 1 : assert_non_null(ptask);
839 1 : assert_non_null(ptask->timer);
840 :
841 1 : next_execution = ptask->next_execution;
842 :
843 4 : while (!is_sync_ptask_finished(test_ctx, ptask)) {
844 2 : tevent_loop_once(test_ctx->be_ctx->ev);
845 : }
846 :
847 1 : assert_true(now <= ptask->last_execution);
848 1 : assert_true(now <= test_ctx->when);
849 1 : assert_true(ptask->last_execution <= test_ctx->when);
850 :
851 1 : assert_true(next_execution + PERIOD <= ptask->next_execution);
852 1 : assert_non_null(ptask->timer);
853 :
854 1 : be_ptask_destroy(&ptask);
855 1 : assert_null(ptask);
856 1 : }
857 :
858 1 : void test_be_ptask_sync_reschedule_error(void **state)
859 : {
860 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
861 1 : struct be_ptask *ptask = NULL;
862 1 : time_t now = 0;
863 : errno_t ret;
864 :
865 1 : ret = be_ptask_create_sync(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
866 : BE_PTASK_OFFLINE_SKIP, 0,
867 : test_be_ptask_sync_error,
868 : test_ctx, "Test ptask", &ptask);
869 1 : assert_int_equal(ret, ERR_OK);
870 1 : assert_non_null(ptask);
871 1 : assert_non_null(ptask->timer);
872 :
873 4 : while (!is_sync_ptask_finished(test_ctx, ptask)) {
874 2 : now = get_current_time();
875 2 : tevent_loop_once(test_ctx->be_ctx->ev);
876 : }
877 :
878 1 : assert_true(now + PERIOD <= ptask->next_execution);
879 1 : assert_non_null(ptask->timer);
880 :
881 1 : be_ptask_destroy(&ptask);
882 1 : assert_null(ptask);
883 1 : }
884 :
885 1 : void test_be_ptask_sync_reschedule_backoff(void **state)
886 : {
887 1 : struct test_ctx *test_ctx = (struct test_ctx *)(*state);
888 1 : struct be_ptask *ptask = NULL;
889 : time_t next_execution;
890 : time_t now_first;
891 1 : time_t now_backoff = 0;
892 : errno_t ret;
893 :
894 1 : now_first = get_current_time();
895 1 : ret = be_ptask_create_sync(test_ctx, test_ctx->be_ctx, PERIOD, 0, 0, 0, 0,
896 : BE_PTASK_OFFLINE_SKIP, PERIOD*2,
897 : test_be_ptask_sync_error,
898 : test_ctx, "Test ptask", &ptask);
899 1 : assert_int_equal(ret, ERR_OK);
900 1 : assert_non_null(ptask);
901 1 : assert_non_null(ptask->timer);
902 :
903 : /* first run */
904 1 : next_execution = ptask->next_execution;
905 :
906 4 : while (!is_sync_ptask_finished(test_ctx, ptask)) {
907 : /* We need to acquire timestamp for the second test here, since this
908 : * is the closest value to the timestamp when the next event is
909 : * scheduled. */
910 2 : now_backoff = get_current_time();
911 2 : tevent_loop_once(test_ctx->be_ctx->ev);
912 : }
913 :
914 1 : assert_true(now_first <= ptask->last_execution);
915 1 : assert_true(now_first <= test_ctx->when);
916 1 : assert_true(ptask->last_execution <= test_ctx->when);
917 :
918 1 : assert_true(next_execution + PERIOD <= ptask->next_execution);
919 1 : assert_int_equal(PERIOD*2, ptask->period);
920 1 : assert_non_null(ptask->timer);
921 :
922 1 : test_ctx->done = false;
923 :
924 : /* second run */
925 1 : next_execution = ptask->next_execution;
926 :
927 4 : while (!is_sync_ptask_finished(test_ctx, ptask)) {
928 2 : tevent_loop_once(test_ctx->be_ctx->ev);
929 : }
930 :
931 1 : assert_true(now_backoff + PERIOD <= ptask->last_execution);
932 1 : assert_true(now_backoff + PERIOD <= test_ctx->when);
933 1 : assert_true(ptask->last_execution <= test_ctx->when);
934 :
935 1 : assert_true(next_execution + PERIOD*2 <= ptask->next_execution);
936 1 : assert_int_equal(PERIOD*2, ptask->period);
937 1 : assert_non_null(ptask->timer);
938 :
939 1 : be_ptask_destroy(&ptask);
940 1 : assert_null(ptask);
941 1 : }
942 :
943 1 : int main(int argc, const char *argv[])
944 : {
945 : poptContext pc;
946 : int opt;
947 6 : struct poptOption long_options[] = {
948 : POPT_AUTOHELP
949 5 : SSSD_DEBUG_OPTS
950 : POPT_TABLEEND
951 : };
952 :
953 1 : const struct CMUnitTest tests[] = {
954 : new_test(be_ptask_create_einval_be),
955 : new_test(be_ptask_create_einval_period),
956 : new_test(be_ptask_create_einval_send),
957 : new_test(be_ptask_create_einval_recv),
958 : new_test(be_ptask_create_einval_name),
959 : new_test(be_ptask_create_no_delay),
960 : new_test(be_ptask_create_first_delay),
961 : new_test(be_ptask_disable),
962 : new_test(be_ptask_enable),
963 : new_test(be_ptask_enable_delay),
964 : new_test(be_ptask_offline_skip),
965 : new_test(be_ptask_offline_disable),
966 : new_test(be_ptask_offline_execute),
967 : new_test(be_ptask_reschedule_ok),
968 : new_test(be_ptask_reschedule_null),
969 : new_test(be_ptask_reschedule_error),
970 : new_test(be_ptask_reschedule_timeout),
971 : new_test(be_ptask_reschedule_backoff),
972 : new_test(be_ptask_get_period),
973 : new_test(be_ptask_create_sync),
974 : new_test(be_ptask_sync_reschedule_ok),
975 : new_test(be_ptask_sync_reschedule_error),
976 : new_test(be_ptask_sync_reschedule_backoff)
977 : };
978 :
979 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
980 1 : debug_level = SSSDBG_INVALID;
981 :
982 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
983 1 : while((opt = poptGetNextOpt(pc)) != -1) {
984 : switch(opt) {
985 : default:
986 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
987 : poptBadOption(pc, 0), poptStrerror(opt));
988 0 : poptPrintUsage(pc, stderr, 0);
989 0 : return 1;
990 : }
991 : }
992 1 : poptFreeContext(pc);
993 :
994 1 : DEBUG_CLI_INIT(debug_level);
995 :
996 1 : return cmocka_run_group_tests(tests, NULL, NULL);
997 : }
|