1 /* 2 * testcode/unitregional.c - unit test for regional allocator. 3 * 4 * Copyright (c) 2010, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 */ 36 /** 37 * \file 38 * Tests the regional special purpose allocator. 39 */ 40 41 #include "config.h" 42 #include "testcode/unitmain.h" 43 #include "util/log.h" 44 #include "util/regional.h" 45 46 /** test regional corner cases, zero, one, end of structure */ 47 static void 48 corner_cases(struct regional* r) 49 { 50 size_t s; /* shadow count of allocated memory */ 51 void* a; 52 size_t minsize = sizeof(uint64_t); 53 size_t mysize; 54 char* str; 55 unit_assert(r); 56 /* alloc cases: 57 * 0, 1, 2. 58 * smaller than LARGE_OBJECT_SIZE. 59 * smaller but does not fit in remainder in regional. 60 * smaller but exactly fits in remainder of regional. 61 * size is remainder of regional - 8. 62 * size is remainder of regional + 8. 63 * larger than LARGE_OBJECT_SIZE. 64 */ 65 s = sizeof(struct regional); 66 unit_assert((s % minsize) == 0); 67 unit_assert(r->available == r->first_size - s); 68 unit_assert(r->large_list == NULL); 69 unit_assert(r->next == NULL); 70 71 /* Note an alloc of 0 gets a pointer to current last 72 * position (where you should then use 0 bytes) */ 73 a = regional_alloc(r, 0); 74 unit_assert(a); 75 s+=0; 76 unit_assert(r->available == r->first_size - s); 77 78 a = regional_alloc(r, 1); 79 unit_assert(a); 80 memset(a, 0x42, 1); 81 s+=minsize; 82 unit_assert(r->available == r->first_size - s); 83 84 a = regional_alloc(r, 2); 85 unit_assert(a); 86 memset(a, 0x42, 2); 87 s+=minsize; 88 unit_assert(r->available == r->first_size - s); 89 90 a = regional_alloc(r, 128); 91 unit_assert(a); 92 memset(a, 0x42, 128); 93 s+=128; 94 unit_assert(r->available == r->first_size - s); 95 96 unit_assert(r->large_list == NULL); 97 a = regional_alloc(r, 10240); 98 unit_assert(a); 99 unit_assert(r->large_list != NULL); 100 memset(a, 0x42, 10240); 101 /* s does not change */ 102 unit_assert(r->available == r->first_size - s); 103 unit_assert(r->total_large == 10240+minsize); 104 105 /* go towards the end of the current chunk */ 106 while(r->available > 1024) { 107 a = regional_alloc(r, 1024); 108 unit_assert(a); 109 memset(a, 0x42, 1024); 110 s += 1024; 111 unit_assert(r->available == r->first_size - s); 112 } 113 114 unit_assert(r->next == NULL); 115 mysize = 1280; /* does not fit in current chunk */ 116 a = regional_alloc(r, mysize); 117 memset(a, 0x42, mysize); 118 unit_assert(r->next != NULL); 119 unit_assert(a); 120 121 /* go towards the end of the current chunk */ 122 while(r->available > 864) { 123 a = regional_alloc(r, 864); 124 unit_assert(a); 125 memset(a, 0x42, 864); 126 s += 864; 127 } 128 129 mysize = r->available; /* exactly fits */ 130 a = regional_alloc(r, mysize); 131 memset(a, 0x42, mysize); 132 unit_assert(a); 133 unit_assert(r->available == 0); /* implementation does not go ahead*/ 134 135 a = regional_alloc(r, 8192); /* another large allocation */ 136 unit_assert(a); 137 memset(a, 0x42, 8192); 138 unit_assert(r->available == 0); 139 unit_assert(r->total_large == 10240 + 8192 + 2*minsize); 140 141 a = regional_alloc(r, 32); /* make new chunk */ 142 unit_assert(a); 143 memset(a, 0x42, 32); 144 unit_assert(r->available > 0); 145 unit_assert(r->total_large == 10240 + 8192 + 2*minsize); 146 147 /* go towards the end of the current chunk */ 148 while(r->available > 1320) { 149 a = regional_alloc(r, 1320); 150 unit_assert(a); 151 memset(a, 0x42, 1320); 152 s += 1320; 153 } 154 155 mysize = r->available + 8; /* exact + 8 ; does not fit */ 156 a = regional_alloc(r, mysize); 157 memset(a, 0x42, mysize); 158 unit_assert(a); 159 unit_assert(r->available > 0); /* new chunk */ 160 161 /* go towards the end of the current chunk */ 162 while(r->available > 1480) { 163 a = regional_alloc(r, 1480); 164 unit_assert(a); 165 memset(a, 0x42, 1480); 166 s += 1480; 167 } 168 169 mysize = r->available - 8; /* exact - 8 ; fits. */ 170 a = regional_alloc(r, mysize); 171 memset(a, 0x42, mysize); 172 unit_assert(a); 173 unit_assert(r->available == 8); 174 175 /* test if really copied over */ 176 str = "test12345"; 177 a = regional_alloc_init(r, str, 8); 178 unit_assert(a); 179 unit_assert(memcmp(a, str, 8) == 0); 180 181 /* test if really zeroed */ 182 a = regional_alloc_zero(r, 32); 183 str="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 184 unit_assert(a); 185 unit_assert(memcmp(a, str, 32) == 0); 186 187 /* test if copied over (and null byte) */ 188 str = "an interesting string"; 189 a = regional_strdup(r, str); 190 unit_assert(a); 191 unit_assert(memcmp(a, str, strlen(str)+1) == 0); 192 193 regional_free_all(r); 194 } 195 196 /** test specific cases */ 197 static void 198 specific_cases(void) 199 { 200 struct regional* r = regional_create(); 201 corner_cases(r); 202 regional_destroy(r); 203 r = regional_create_custom(2048); /* a small regional */ 204 unit_assert(r->first_size == 2048); 205 unit_assert(regional_get_mem(r) == 2048); 206 corner_cases(r); 207 unit_assert(regional_get_mem(r) == 2048); 208 regional_destroy(r); 209 } 210 211 /** put random stuff in a region and free it */ 212 static void 213 burden_test(size_t max) 214 { 215 size_t get; 216 void* a; 217 int i; 218 struct regional* r = regional_create_custom(2048); 219 for(i=0; i<1000; i++) { 220 get = random() % max; 221 a = regional_alloc(r, get); 222 unit_assert(a); 223 memset(a, 0x54, get); 224 } 225 regional_free_all(r); 226 regional_destroy(r); 227 } 228 229 /** randomly allocate stuff */ 230 static void 231 random_burden(void) 232 { 233 size_t max_alloc = 2048 + 128; /* small chance of LARGE */ 234 int i; 235 for(i=0; i<100; i++) 236 burden_test(max_alloc); 237 } 238 239 void regional_test(void) 240 { 241 unit_show_feature("regional"); 242 specific_cases(); 243 random_burden(); 244 } 245