]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/lib/isc/tests/task_test.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / lib / isc / tests / task_test.c
1 /*
2  * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /* $Id$ */
18
19 /*! \file */
20
21 #include <config.h>
22
23 #include <atf-c.h>
24
25 #include <unistd.h>
26
27 #include <isc/task.h>
28 #include <isc/util.h>
29
30 #include "../task_p.h"
31 #include "isctest.h"
32
33 /*
34  * Helper functions
35  */
36
37 /* task event handler, sets a boolean to true */
38 int counter = 0;
39 isc_mutex_t set_lock;
40
41 static void
42 set(isc_task_t *task, isc_event_t *event) {
43         int *value = (int *) event->ev_arg;
44
45         UNUSED(task);
46
47         isc_event_free(&event);
48         LOCK(&set_lock);
49         *value = counter++;
50         UNLOCK(&set_lock);
51 }
52
53 static void
54 set_and_drop(isc_task_t *task, isc_event_t *event) {
55         int *value = (int *) event->ev_arg;
56
57         UNUSED(task);
58
59         isc_event_free(&event);
60         LOCK(&set_lock);
61         *value = (int) isc_taskmgr_mode(taskmgr);
62         counter++;
63         UNLOCK(&set_lock);
64         isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_normal);
65 }
66
67 /*
68  * Individual unit tests
69  */
70
71 /* Create a task */
72 ATF_TC(create_task);
73 ATF_TC_HEAD(create_task, tc) {
74         atf_tc_set_md_var(tc, "descr", "create and destroy a task");
75 }
76 ATF_TC_BODY(create_task, tc) {
77         isc_result_t result;
78         isc_task_t *task = NULL;
79
80         UNUSED(tc);
81
82         result = isc_test_begin(NULL, ISC_TRUE);
83         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
84
85         result = isc_task_create(taskmgr, 0, &task);
86         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
87
88         isc_task_destroy(&task);
89         ATF_REQUIRE_EQ(task, NULL);
90
91         isc_test_end();
92 }
93
94 /* Process events */
95 ATF_TC(all_events);
96 ATF_TC_HEAD(all_events, tc) {
97         atf_tc_set_md_var(tc, "descr", "process task events");
98 }
99 ATF_TC_BODY(all_events, tc) {
100         isc_result_t result;
101         isc_task_t *task = NULL;
102         isc_event_t *event;
103         int a = 0, b = 0;
104         int i = 0;
105
106         UNUSED(tc);
107
108         counter = 1;
109
110         result = isc_mutex_init(&set_lock);
111         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
112
113         result = isc_test_begin(NULL, ISC_TRUE);
114         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
115
116         result = isc_task_create(taskmgr, 0, &task);
117         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
118
119         /* First event */
120         event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST,
121                                    set, &a, sizeof (isc_event_t));
122         ATF_REQUIRE(event != NULL);
123
124         ATF_CHECK_EQ(a, 0);
125         isc_task_send(task, &event);
126
127         event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST,
128                                    set, &b, sizeof (isc_event_t));
129         ATF_REQUIRE(event != NULL);
130
131         ATF_CHECK_EQ(b, 0);
132         isc_task_send(task, &event);
133
134         while ((a == 0 || b == 0) && i++ < 5000) {
135 #ifndef ISC_PLATFORM_USETHREADS
136                 while (isc__taskmgr_ready(taskmgr))
137                         isc__taskmgr_dispatch(taskmgr);
138 #endif
139                 isc_test_nap(1000);
140         }
141
142         ATF_CHECK(a != 0);
143         ATF_CHECK(b != 0);
144
145         isc_task_destroy(&task);
146         ATF_REQUIRE_EQ(task, NULL);
147
148         isc_test_end();
149 }
150
151 /* Privileged events */
152 ATF_TC(privileged_events);
153 ATF_TC_HEAD(privileged_events, tc) {
154         atf_tc_set_md_var(tc, "descr", "process privileged events");
155 }
156 ATF_TC_BODY(privileged_events, tc) {
157         isc_result_t result;
158         isc_task_t *task1 = NULL, *task2 = NULL;
159         isc_event_t *event;
160         int a = 0, b = 0, c = 0, d = 0, e = 0;
161         int i = 0;
162
163         UNUSED(tc);
164
165         counter = 1;
166         result = isc_mutex_init(&set_lock);
167         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
168
169         result = isc_test_begin(NULL, ISC_TRUE);
170         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
171
172 #ifdef ISC_PLATFORM_USETHREADS
173         /*
174          * Pause the task manager so we can fill up the work queue
175          * without things happening while we do it.
176          */
177         isc__taskmgr_pause(taskmgr);
178 #endif
179
180         result = isc_task_create(taskmgr, 0, &task1);
181         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
182         isc_task_setname(task1, "privileged", NULL);
183         ATF_CHECK(!isc_task_privilege(task1));
184         isc_task_setprivilege(task1, ISC_TRUE);
185         ATF_CHECK(isc_task_privilege(task1));
186
187         result = isc_task_create(taskmgr, 0, &task2);
188         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
189         isc_task_setname(task2, "normal", NULL);
190         ATF_CHECK(!isc_task_privilege(task2));
191
192         /* First event: privileged */
193         event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
194                                    set, &a, sizeof (isc_event_t));
195         ATF_REQUIRE(event != NULL);
196
197         ATF_CHECK_EQ(a, 0);
198         isc_task_send(task1, &event);
199
200         /* Second event: not privileged */
201         event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
202                                    set, &b, sizeof (isc_event_t));
203         ATF_REQUIRE(event != NULL);
204
205         ATF_CHECK_EQ(b, 0);
206         isc_task_send(task2, &event);
207
208         /* Third event: privileged */
209         event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
210                                    set, &c, sizeof (isc_event_t));
211         ATF_REQUIRE(event != NULL);
212
213         ATF_CHECK_EQ(c, 0);
214         isc_task_send(task1, &event);
215
216         /* Fourth event: privileged */
217         event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
218                                    set, &d, sizeof (isc_event_t));
219         ATF_REQUIRE(event != NULL);
220
221         ATF_CHECK_EQ(d, 0);
222         isc_task_send(task1, &event);
223
224         /* Fifth event: not privileged */
225         event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
226                                    set, &e, sizeof (isc_event_t));
227         ATF_REQUIRE(event != NULL);
228
229         ATF_CHECK_EQ(e, 0);
230         isc_task_send(task2, &event);
231
232         ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
233         isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
234         ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_privileged);
235
236 #ifdef ISC_PLATFORM_USETHREADS
237         isc__taskmgr_resume(taskmgr);
238 #endif
239
240         /* We're waiting for *all* variables to be set */
241         while ((a == 0 || b == 0 || c == 0 || d == 0 || e == 0) && i++ < 5000) {
242 #ifndef ISC_PLATFORM_USETHREADS
243                 while (isc__taskmgr_ready(taskmgr))
244                         isc__taskmgr_dispatch(taskmgr);
245 #endif
246                 isc_test_nap(1000);
247         }
248
249         /*
250          * We can't guarantee what order the events fire, but
251          * we do know the privileged tasks that set a, c, and d
252          * would have fired first.
253          */
254         ATF_CHECK(a <= 3);
255         ATF_CHECK(c <= 3);
256         ATF_CHECK(d <= 3);
257
258         /* ...and the non-privileged tasks that set b and e, last */
259         ATF_CHECK(b >= 4);
260         ATF_CHECK(e >= 4);
261
262         ATF_CHECK_EQ(counter, 6);
263
264         isc_task_setprivilege(task1, ISC_FALSE);
265         ATF_CHECK(!isc_task_privilege(task1));
266
267         ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
268
269         isc_task_destroy(&task1);
270         ATF_REQUIRE_EQ(task1, NULL);
271         isc_task_destroy(&task2);
272         ATF_REQUIRE_EQ(task2, NULL);
273
274         isc_test_end();
275 }
276
277 /*
278  * Edge case: this tests that the task manager behaves as expected when
279  * we explicitly set it into normal mode *while* running privileged.
280  */
281 ATF_TC(privilege_drop);
282 ATF_TC_HEAD(privilege_drop, tc) {
283         atf_tc_set_md_var(tc, "descr", "process privileged events");
284 }
285 ATF_TC_BODY(privilege_drop, tc) {
286         isc_result_t result;
287         isc_task_t *task1 = NULL, *task2 = NULL;
288         isc_event_t *event;
289         int a = -1, b = -1, c = -1, d = -1, e = -1;     /* non valid states */
290         int i = 0;
291
292         UNUSED(tc);
293
294         counter = 1;
295         result = isc_mutex_init(&set_lock);
296         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
297
298         result = isc_test_begin(NULL, ISC_TRUE);
299         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
300
301 #ifdef ISC_PLATFORM_USETHREADS
302         /*
303          * Pause the task manager so we can fill up the work queue
304          * without things happening while we do it.
305          */
306         isc__taskmgr_pause(taskmgr);
307 #endif
308
309         result = isc_task_create(taskmgr, 0, &task1);
310         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
311         isc_task_setname(task1, "privileged", NULL);
312         ATF_CHECK(!isc_task_privilege(task1));
313         isc_task_setprivilege(task1, ISC_TRUE);
314         ATF_CHECK(isc_task_privilege(task1));
315
316         result = isc_task_create(taskmgr, 0, &task2);
317         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
318         isc_task_setname(task2, "normal", NULL);
319         ATF_CHECK(!isc_task_privilege(task2));
320
321         /* First event: privileged */
322         event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
323                                    set_and_drop, &a, sizeof (isc_event_t));
324         ATF_REQUIRE(event != NULL);
325
326         ATF_CHECK_EQ(a, -1);
327         isc_task_send(task1, &event);
328
329         /* Second event: not privileged */
330         event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
331                                    set_and_drop, &b, sizeof (isc_event_t));
332         ATF_REQUIRE(event != NULL);
333
334         ATF_CHECK_EQ(b, -1);
335         isc_task_send(task2, &event);
336
337         /* Third event: privileged */
338         event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
339                                    set_and_drop, &c, sizeof (isc_event_t));
340         ATF_REQUIRE(event != NULL);
341
342         ATF_CHECK_EQ(c, -1);
343         isc_task_send(task1, &event);
344
345         /* Fourth event: privileged */
346         event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
347                                    set_and_drop, &d, sizeof (isc_event_t));
348         ATF_REQUIRE(event != NULL);
349
350         ATF_CHECK_EQ(d, -1);
351         isc_task_send(task1, &event);
352
353         /* Fifth event: not privileged */
354         event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
355                                    set_and_drop, &e, sizeof (isc_event_t));
356         ATF_REQUIRE(event != NULL);
357
358         ATF_CHECK_EQ(e, -1);
359         isc_task_send(task2, &event);
360
361         ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
362         isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
363         ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_privileged);
364
365 #ifdef ISC_PLATFORM_USETHREADS
366         isc__taskmgr_resume(taskmgr);
367 #endif
368
369         /* We're waiting for all variables to be set. */
370         while ((a == -1 || b == -1 || c == -1 || d == -1 || e == -1) &&
371                i++ < 5000) {
372 #ifndef ISC_PLATFORM_USETHREADS
373                 while (isc__taskmgr_ready(taskmgr))
374                         isc__taskmgr_dispatch(taskmgr);
375 #endif
376                 isc_test_nap(1000);
377         }
378
379         /*
380          * We can't guarantee what order the events fire, but
381          * we do know *exactly one* of the privileged tasks will
382          * have run in privileged mode...
383          */
384         ATF_CHECK(a == isc_taskmgrmode_privileged ||
385                   c == isc_taskmgrmode_privileged ||
386                   d == isc_taskmgrmode_privileged);
387         ATF_CHECK(a + c + d == isc_taskmgrmode_privileged);
388
389         /* ...and neither of the non-privileged tasks did... */
390         ATF_CHECK(b == isc_taskmgrmode_normal || e == isc_taskmgrmode_normal);
391
392         /* ...but all five of them did run. */
393         ATF_CHECK_EQ(counter, 6);
394
395         ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
396
397         isc_task_destroy(&task1);
398         ATF_REQUIRE_EQ(task1, NULL);
399         isc_task_destroy(&task2);
400         ATF_REQUIRE_EQ(task2, NULL);
401
402         isc_test_end();
403 }
404
405 /*
406  * Main
407  */
408 ATF_TP_ADD_TCS(tp) {
409         ATF_TP_ADD_TC(tp, create_task);
410         ATF_TP_ADD_TC(tp, all_events);
411         ATF_TP_ADD_TC(tp, privileged_events);
412         ATF_TP_ADD_TC(tp, privilege_drop);
413
414         return (atf_no_error());
415 }
416