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 <time.h> 24 25#include <isc/app.h> 26#include <isc/buffer.h> 27#include <isc/entropy.h> 28#include <isc/hash.h> 29#include <isc/mem.h> 30#include <isc/os.h> 31#include <isc/socket.h> 32#include <isc/string.h> 33#include <isc/task.h> 34#include <isc/timer.h> 35#include <isc/util.h> 36 37#include "isctest.h" 38 39isc_mem_t *mctx = NULL; 40isc_entropy_t *ectx = NULL; 41isc_log_t *lctx = NULL; 42isc_taskmgr_t *taskmgr = NULL; 43isc_timermgr_t *timermgr = NULL; 44isc_socketmgr_t *socketmgr = NULL; 45int ncpus; 46 47static isc_boolean_t hash_active = ISC_FALSE; 48 49/* 50 * Logging categories: this needs to match the list in bin/named/log.c. 51 */ 52static isc_logcategory_t categories[] = { 53 { "", 0 }, 54 { "client", 0 }, 55 { "network", 0 }, 56 { "update", 0 }, 57 { "queries", 0 }, 58 { "unmatched", 0 }, 59 { "update-security", 0 }, 60 { "query-errors", 0 }, 61 { NULL, 0 } 62}; 63 64static void 65cleanup_managers() { 66 if (socketmgr != NULL) 67 isc_socketmgr_destroy(&socketmgr); 68 if (taskmgr != NULL) 69 isc_taskmgr_destroy(&taskmgr); 70 if (timermgr != NULL) 71 isc_timermgr_destroy(&timermgr); 72} 73 74static isc_result_t 75create_managers() { 76 isc_result_t result; 77#ifdef ISC_PLATFORM_USETHREADS 78 ncpus = isc_os_ncpus(); 79#else 80 ncpus = 1; 81#endif 82 83 CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr)); 84 CHECK(isc_timermgr_create(mctx, &timermgr)); 85 CHECK(isc_socketmgr_create(mctx, &socketmgr)); 86 return (ISC_R_SUCCESS); 87 88 cleanup: 89 cleanup_managers(); 90 return (result); 91} 92 93isc_result_t 94isc_test_begin(FILE *logfile, isc_boolean_t start_managers) { 95 isc_result_t result; 96 97 isc_mem_debugging |= ISC_MEM_DEBUGRECORD; 98 CHECK(isc_mem_create(0, 0, &mctx)); 99 CHECK(isc_entropy_create(mctx, &ectx)); 100 101 CHECK(isc_hash_create(mctx, ectx, 255)); 102 hash_active = ISC_TRUE; 103 104 if (logfile != NULL) { 105 isc_logdestination_t destination; 106 isc_logconfig_t *logconfig = NULL; 107 108 CHECK(isc_log_create(mctx, &lctx, &logconfig)); 109 isc_log_registercategories(lctx, categories); 110 isc_log_setcontext(lctx); 111 112 destination.file.stream = logfile; 113 destination.file.name = NULL; 114 destination.file.versions = ISC_LOG_ROLLNEVER; 115 destination.file.maximum_size = 0; 116 CHECK(isc_log_createchannel(logconfig, "stderr", 117 ISC_LOG_TOFILEDESC, 118 ISC_LOG_DYNAMIC, 119 &destination, 0)); 120 CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL)); 121 } 122 123#ifdef ISC_PLATFORM_USETHREADS 124 ncpus = isc_os_ncpus(); 125#else 126 ncpus = 1; 127#endif 128 129 if (start_managers) 130 CHECK(create_managers()); 131 132 return (ISC_R_SUCCESS); 133 134 cleanup: 135 isc_test_end(); 136 return (result); 137} 138 139void 140isc_test_end() { 141 if (taskmgr != NULL) 142 isc_taskmgr_destroy(&taskmgr); 143 if (lctx != NULL) 144 isc_log_destroy(&lctx); 145 if (hash_active) { 146 isc_hash_destroy(); 147 hash_active = ISC_FALSE; 148 } 149 if (ectx != NULL) 150 isc_entropy_detach(&ectx); 151 152 cleanup_managers(); 153 154 if (mctx != NULL) 155 isc_mem_destroy(&mctx); 156} 157 158/* 159 * Sleep for 'usec' microseconds. 160 */ 161void 162isc_test_nap(isc_uint32_t usec) { 163#ifdef HAVE_NANOSLEEP 164 struct timespec ts; 165 166 ts.tv_sec = usec / 1000000; 167 ts.tv_nsec = (usec % 1000000) * 1000; 168 nanosleep(&ts, NULL); 169#elif HAVE_USLEEP 170 usleep(usec); 171#else 172 /* 173 * No fractional-second sleep function is available, so we 174 * round up to the nearest second and sleep instead 175 */ 176 sleep((usec / 1000000) + 1); 177#endif 178} 179