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