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 */ 38int counter = 0; 39isc_mutex_t set_lock; 40 41static void 42set(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 53static void 54set_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 */ 72ATF_TC(create_task); 73ATF_TC_HEAD(create_task, tc) { 74 atf_tc_set_md_var(tc, "descr", "create and destroy a task"); 75} 76ATF_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 */ 95ATF_TC(all_events); 96ATF_TC_HEAD(all_events, tc) { 97 atf_tc_set_md_var(tc, "descr", "process task events"); 98} 99ATF_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 */ 152ATF_TC(privileged_events); 153ATF_TC_HEAD(privileged_events, tc) { 154 atf_tc_set_md_var(tc, "descr", "process privileged events"); 155} 156ATF_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 */ 281ATF_TC(privilege_drop); 282ATF_TC_HEAD(privilege_drop, tc) { 283 atf_tc_set_md_var(tc, "descr", "process privileged events"); 284} 285ATF_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 */ 408ATF_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 417