1/* $NetBSD: leaseq_unittest.c,v 1.2 2018/04/07 22:37:30 christos Exp $ */ 2 3/* 4 * Copyright (C) 2015-2017 by Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 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#include <config.h> 20 21#include "dhcpd.h" 22 23#include <atf-c.h> 24 25/* 26 * Test the lease queue code. These tests will verify that we can 27 * add, find and remove leases from the lease queue code 28 * 29 * Thoughout the tests 30 * lq will be the lease queue for which we add or removing leases 31 * test_leaseX will be the leases we add or remove 32 * We only care about the sort_time in the lease structure for these 33 * tests but need to do a lease_reference in order to keep the ref 34 * count positive to avoid the omapi code trying to free the object. 35 * We can't use lease_allocate easily as we haven't set up the omapi 36 * object information in the test. 37 */ 38 39#if defined (BINARY_LEASES) 40#define INIT_LQ(LQ) memset(&(LQ), 0, sizeof(struct leasechain)) 41#else 42#define INIT_LQ(LQ) lq = NULL 43#endif 44 45/* Test basic leaseq functions with a single lease */ 46/*- empty, add, get, and remove */ 47ATF_TC(leaseq_basic); 48ATF_TC_HEAD(leaseq_basic, tc) 49{ 50 atf_tc_set_md_var(tc, "descr", "Verify basic functions"); 51} 52 53ATF_TC_BODY(leaseq_basic, tc) 54{ 55 LEASE_STRUCT lq; 56 struct lease test_lease1, *check_lease; 57 58 INIT_LQ(lq); 59 60 memset(&test_lease1, 0, sizeof(struct lease)); 61 test_lease1.sort_time = 10; 62 check_lease = NULL; 63 lease_reference(&check_lease, &test_lease1, MDL); 64 65 /* Check that the lq is empty */ 66 if ((LEASE_NOT_EMPTY(lq)) || (LEASE_NOT_EMPTYP(&lq))) 67 atf_tc_fail("lq not empty at start."); 68 69 /* And that getting the first lease is okay when queue is empty */ 70 if ((LEASE_GET_FIRST(lq) != NULL) || (LEASE_GET_FIRSTP(&lq) != NULL)) 71 atf_tc_fail("lease not null"); 72 73 /* Add a lease */ 74 LEASE_INSERTP(&lq, &test_lease1); 75 76 /* lq shouldn't be empty anymore */ 77 if (!(LEASE_NOT_EMPTY(lq)) || !(LEASE_NOT_EMPTYP(&lq))) 78 atf_tc_fail("lq empty after insertion."); 79 80 /* We should have the same lease we inserted */ 81 check_lease = LEASE_GET_FIRST(lq); 82 if (check_lease != &test_lease1) 83 atf_tc_fail("leases don't match"); 84 85 /* We should have the same lease we inserted */ 86 check_lease = LEASE_GET_FIRSTP(&lq); 87 if (check_lease != &test_lease1) 88 atf_tc_fail("leases don't match"); 89 90 /* Check that doing a get on the last lease returns NULL */ 91 if ((LEASE_GET_NEXT(lq, check_lease) != NULL) || 92 (LEASE_GET_NEXTP(&lq, check_lease) != NULL)) { 93 atf_tc_fail("Next not null"); 94 } 95 96 /* Remove the lease */ 97 LEASE_REMOVEP(&lq, &test_lease1); 98 99 /* and verify the lease queue is empty again */ 100 if ((LEASE_NOT_EMPTY(lq)) || (LEASE_NOT_EMPTYP(&lq))) 101 atf_tc_fail("lq not empty afer removal"); 102 103 /* And that getting the first lease is okay when queue is empty */ 104 if ((LEASE_GET_FIRST(lq) != NULL) || (LEASE_GET_FIRSTP(&lq) != NULL)) 105 atf_tc_fail("lease not null"); 106} 107 108/* Test if we can add leases to the end of the list and remove them 109 * from the end */ 110ATF_TC(leaseq_add_to_end); 111ATF_TC_HEAD(leaseq_add_to_end, tc) 112{ 113 atf_tc_set_md_var(tc, "descr", "Verify adding to end of list"); 114} 115 116ATF_TC_BODY(leaseq_add_to_end, tc) 117{ 118 LEASE_STRUCT lq; 119 struct lease test_lease[3], *check_lease; 120 int i; 121 122 INIT_LQ(lq); 123 124 /* create and add 3 leases */ 125 for (i = 0; i < 3; i++) { 126 memset(&test_lease[i], 0, sizeof(struct lease)); 127 test_lease[i].sort_time = i; 128 check_lease = NULL; 129 lease_reference(&check_lease, &test_lease[i], MDL); 130 LEASE_INSERTP(&lq, &test_lease[i]); 131 } 132 133 /* check ordering of leases */ 134 check_lease = LEASE_GET_FIRST(lq); 135 for (i = 0; i < 3; i++) { 136 if (check_lease != &test_lease[i]) 137 atf_tc_fail("leases don't match, %d", i); 138 check_lease = LEASE_GET_NEXT(lq, check_lease); 139 } 140 if (check_lease != NULL) 141 atf_tc_fail("lease not null"); 142 143 /* Remove the last lease and check the list */ 144 LEASE_REMOVEP(&lq, &test_lease[2]); 145 check_lease = LEASE_GET_FIRST(lq); 146 if (check_lease != &test_lease[0]) 147 atf_tc_fail("wrong lease after remove, 1"); 148 check_lease = LEASE_GET_NEXT(lq, check_lease); 149 if (check_lease != &test_lease[1]) 150 atf_tc_fail("wrong lease after remove, 2"); 151 152 LEASE_REMOVEP(&lq, &test_lease[1]); 153 check_lease = LEASE_GET_FIRST(lq); 154 if (check_lease != &test_lease[0]) 155 atf_tc_fail("wrong lease after remove, 3"); 156 157 LEASE_REMOVEP(&lq, check_lease); 158 159 /* The lease queue should now be empty */ 160 if (LEASE_NOT_EMPTY(lq)) 161 atf_tc_fail("lq not empty afer removal"); 162} 163 164/* Test if we can add leases to the start of the list and remove them 165 * from the start */ 166ATF_TC(leaseq_add_to_start); 167ATF_TC_HEAD(leaseq_add_to_start, tc) 168{ 169 atf_tc_set_md_var(tc, "descr", "Verify adding to start of list"); 170} 171 172ATF_TC_BODY(leaseq_add_to_start, tc) 173{ 174 LEASE_STRUCT lq; 175 struct lease test_lease[3], *check_lease; 176 int i; 177 178 INIT_LQ(lq); 179 180 /* create 3 leases */ 181 for (i = 0; i < 3; i++) { 182 memset(&test_lease[i], 0, sizeof(struct lease)); 183 test_lease[i].sort_time = i; 184 check_lease = NULL; 185 lease_reference(&check_lease, &test_lease[i], MDL); 186 } 187 188 /* Add leases */ 189 LEASE_INSERTP(&lq, &test_lease[2]); 190 LEASE_INSERTP(&lq, &test_lease[1]); 191 LEASE_INSERTP(&lq, &test_lease[0]); 192 193 /* check ordering of leases */ 194 check_lease = LEASE_GET_FIRST(lq); 195 for (i = 0; i < 3; i++) { 196 if (check_lease != &test_lease[i]) 197 atf_tc_fail("leases don't match, %d", i); 198 check_lease = LEASE_GET_NEXT(lq, check_lease); 199 } 200 if (check_lease != NULL) 201 atf_tc_fail("lease not null"); 202 203 /* Remove the first lease and check the next one */ 204 check_lease = LEASE_GET_FIRST(lq); 205 LEASE_REMOVEP(&lq, check_lease); 206 check_lease = LEASE_GET_FIRST(lq); 207 if (check_lease != &test_lease[1]) 208 atf_tc_fail("wrong lease after remove, 1"); 209 check_lease = LEASE_GET_NEXT(lq, check_lease); 210 if (check_lease != &test_lease[2]) 211 atf_tc_fail("wrong lease after remove, 2"); 212 213 check_lease = LEASE_GET_FIRST(lq); 214 LEASE_REMOVEP(&lq, check_lease); 215 check_lease = LEASE_GET_FIRST(lq); 216 if (check_lease != &test_lease[2]) 217 atf_tc_fail("wrong lease after remove, 3"); 218 219 LEASE_REMOVEP(&lq, check_lease); 220 221 /* The lease queue should now be empty */ 222 if (LEASE_NOT_EMPTY(lq)) 223 atf_tc_fail("lq not empty afer removal"); 224} 225 226/* Test if we can add leases to the middle of the list and remove them 227 * from the middle */ 228ATF_TC(leaseq_add_to_middle); 229ATF_TC_HEAD(leaseq_add_to_middle, tc) 230{ 231 atf_tc_set_md_var(tc, "descr", "Verify adding to end of list"); 232} 233 234ATF_TC_BODY(leaseq_add_to_middle, tc) 235{ 236 LEASE_STRUCT lq; 237 struct lease test_lease[3], *check_lease; 238 int i; 239 240 INIT_LQ(lq); 241 242 /* create 3 leases */ 243 for (i = 0; i < 3; i++) { 244 memset(&test_lease[i], 0, sizeof(struct lease)); 245 test_lease[i].sort_time = i; 246 check_lease = NULL; 247 lease_reference(&check_lease, &test_lease[i], MDL); 248 } 249 250 /* Add leases */ 251 LEASE_INSERTP(&lq, &test_lease[0]); 252 LEASE_INSERTP(&lq, &test_lease[2]); 253 LEASE_INSERTP(&lq, &test_lease[1]); 254 255 /* check ordering of leases */ 256 check_lease = LEASE_GET_FIRST(lq); 257 for (i = 0; i < 3; i++) { 258 if (check_lease != &test_lease[i]) 259 atf_tc_fail("leases don't match, %d", i); 260 check_lease = LEASE_GET_NEXT(lq, check_lease); 261 } 262 if (check_lease != NULL) 263 atf_tc_fail("lease not null"); 264 265 /* Remove the middle lease and check the list */ 266 LEASE_REMOVEP(&lq, &test_lease[1]); 267 check_lease = LEASE_GET_FIRST(lq); 268 if (check_lease != &test_lease[0]) 269 atf_tc_fail("wrong lease after remove, 1"); 270 check_lease = LEASE_GET_NEXT(lq, check_lease); 271 if (check_lease != &test_lease[2]) 272 atf_tc_fail("wrong lease after remove, 2"); 273 274 LEASE_REMOVEP(&lq, &test_lease[0]); 275 check_lease = LEASE_GET_FIRST(lq); 276 if (check_lease != &test_lease[2]) 277 atf_tc_fail("wrong lease after remove, 3"); 278 279 LEASE_REMOVEP(&lq, check_lease); 280 281 /* The lease queue should now be empty */ 282 if (LEASE_NOT_EMPTY(lq)) 283 atf_tc_fail("lq not empty afer removal"); 284} 285 286/* Test if we can cycle the leases we add three leases then remove 287 * the first one, update it's sort time and re add it */ 288ATF_TC(leaseq_cycle); 289ATF_TC_HEAD(leaseq_cycle, tc) 290{ 291 atf_tc_set_md_var(tc, "descr", "Verify cycling the list"); 292} 293 294ATF_TC_BODY(leaseq_cycle, tc) 295{ 296 LEASE_STRUCT lq; 297 struct lease test_lease[3], *check_lease; 298 int i; 299 300 INIT_LQ(lq); 301 302 /* create and add 3 leases */ 303 for (i = 0; i < 3; i++) { 304 memset(&test_lease[i], 0, sizeof(struct lease)); 305 test_lease[i].sort_time = i; 306 check_lease = NULL; 307 lease_reference(&check_lease, &test_lease[i], MDL); 308 LEASE_INSERTP(&lq, &test_lease[i]); 309 } 310 311 /* Remove first lease, update it and re-insert it */ 312 LEASE_REMOVEP(&lq, &test_lease[0]); 313 test_lease[0].sort_time = 4; 314 LEASE_INSERTP(&lq, &test_lease[0]); 315 316 /* check ordering of leases */ 317 check_lease = LEASE_GET_FIRST(lq); 318 if (check_lease != &test_lease[1]) 319 atf_tc_fail("leases don't match, 1"); 320 check_lease = LEASE_GET_NEXT(lq, check_lease); 321 if (check_lease != &test_lease[2]) 322 atf_tc_fail("leases don't match, 2"); 323 check_lease = LEASE_GET_NEXT(lq, check_lease); 324 if (check_lease != &test_lease[0]) 325 atf_tc_fail("leases don't match, 3"); 326 327 /* Remove first lease, update it and re-insert it */ 328 LEASE_REMOVEP(&lq, &test_lease[1]); 329 test_lease[1].sort_time = 5; 330 LEASE_INSERTP(&lq, &test_lease[1]); 331 332 /* check ordering of leases */ 333 check_lease = LEASE_GET_FIRST(lq); 334 if (check_lease != &test_lease[2]) 335 atf_tc_fail("leases don't match, 4"); 336 check_lease = LEASE_GET_NEXT(lq, check_lease); 337 if (check_lease != &test_lease[0]) 338 atf_tc_fail("leases don't match, 5"); 339 check_lease = LEASE_GET_NEXT(lq, check_lease); 340 if (check_lease != &test_lease[1]) 341 atf_tc_fail("leases don't match, 6"); 342 343 /* Remove first lease, update it and re-insert it */ 344 LEASE_REMOVEP(&lq, &test_lease[2]); 345 test_lease[2].sort_time = 6; 346 LEASE_INSERTP(&lq, &test_lease[2]); 347 348 /* check ordering of leases */ 349 check_lease = LEASE_GET_FIRST(lq); 350 if (check_lease != &test_lease[0]) 351 atf_tc_fail("leases don't match, 7"); 352 check_lease = LEASE_GET_NEXT(lq, check_lease); 353 if (check_lease != &test_lease[1]) 354 atf_tc_fail("leases don't match, 8"); 355 check_lease = LEASE_GET_NEXT(lq, check_lease); 356 if (check_lease != &test_lease[2]) 357 atf_tc_fail("leases don't match, 9"); 358} 359 360/* Test what happens if we set the growth factor to a smallish number 361 * and add enough leases to require it to grow multiple times 362 * Mostly this is for the binary leases case but we can most of the 363 * test for both. 364 */ 365 366ATF_TC(leaseq_long); 367ATF_TC_HEAD(leaseq_long, tc) 368{ 369 atf_tc_set_md_var(tc, "descr", "Verify a long list"); 370} 371 372ATF_TC_BODY(leaseq_long, tc) 373{ 374 LEASE_STRUCT lq; 375 struct lease test_lease[20], *check_lease; 376 int i; 377 378 INIT_LQ(lq); 379#if defined (BINARY_LEASES) 380 lc_init_growth(&lq, 5); 381#endif 382 383 /* create and add 10 leases */ 384 for (i = 0; i < 10; i++) { 385 memset(&test_lease[i], 0, sizeof(struct lease)); 386 test_lease[i].sort_time = i; 387 check_lease = NULL; 388 lease_reference(&check_lease, &test_lease[i], MDL); 389 390 LEASE_INSERTP(&lq, &test_lease[i]); 391 } 392 393 /* check ordering of leases */ 394 check_lease = LEASE_GET_FIRST(lq); 395 for (i = 0; i < 10; i++) { 396 if (check_lease != &test_lease[i]) 397 atf_tc_fail("leases don't match, %d", i); 398 check_lease = LEASE_GET_NEXT(lq, check_lease); 399 } 400 401 /* Remove first 5 */ 402 for (i = 0; i < 5; i++) { 403 LEASE_REMOVEP(&lq, &test_lease[i]); 404 } 405 406 /* Add 10 more */ 407 for (i = 10; i < 20; i++) { 408 memset(&test_lease[i], 0, sizeof(struct lease)); 409 test_lease[i].sort_time = i; 410 check_lease = NULL; 411 lease_reference(&check_lease, &test_lease[i], MDL); 412 413 LEASE_INSERTP(&lq, &test_lease[i]); 414 } 415 416 /* and the first 5 */ 417 for (i = 0; i < 5; i++) { 418 LEASE_INSERTP(&lq, &test_lease[i]); 419 } 420 421 /* and check them all out */ 422 check_lease = LEASE_GET_FIRST(lq); 423 for (i = 0; i < 20; i++) { 424 if (check_lease != &test_lease[i]) 425 atf_tc_fail("leases don't match, %d", i); 426 check_lease = LEASE_GET_NEXT(lq, check_lease); 427 } 428} 429 430/* Test if we can add leases that all have the same sort time 431 */ 432ATF_TC(leaseq_same_time); 433ATF_TC_HEAD(leaseq_same_time, tc) 434{ 435 atf_tc_set_md_var(tc, "descr", "Verify adding leases with same time"); 436} 437 438ATF_TC_BODY(leaseq_same_time, tc) 439{ 440 LEASE_STRUCT lq; 441 struct lease test_lease[20], *check_lease; 442 int i; 443 444 INIT_LQ(lq); 445 446 /* create and add 20 leases */ 447 for (i = 0; i < 20; i++) { 448 memset(&test_lease[i], 0, sizeof(struct lease)); 449 if (i < 10) 450 test_lease[i].sort_time = 10; 451 else 452 test_lease[i].sort_time = 20; 453 check_lease = NULL; 454 lease_reference(&check_lease, &test_lease[i], MDL); 455 LEASE_INSERTP(&lq, &test_lease[i]); 456 } 457 458#if defined (BINARY_LEASES) 459 /* the ordering isn't well defined for either but we check 460 * to see what happens in the binary case. At the start 461 * the leases should stay in the order they were added. 462 */ 463 464 /* check ordering of leases */ 465 check_lease = LEASE_GET_FIRST(lq); 466 for (i = 0; i < 20; i++) { 467 if (check_lease != &test_lease[i]) 468 atf_tc_fail("leases don't match 1, %d", i); 469 check_lease = LEASE_GET_NEXT(lq, check_lease); 470 } 471 if (check_lease != NULL) 472 atf_tc_fail("lease not null"); 473#endif 474 475 /* Remove first 10, update their time, but still before 476 * the previous 10 and re add them */ 477 for (i = 0; i < 10; i++) { 478 LEASE_REMOVEP(&lq, &test_lease[i]); 479 test_lease[i].sort_time = 15; 480 LEASE_INSERTP(&lq, &test_lease[i]); 481 } 482 483 /* The ordering becomes random at this point so we don't 484 * check it. We try to remove them all and see that 485 * we got to an empty queue. 486 */ 487 for (i = 0; i < 20; i++) { 488 LEASE_REMOVEP(&lq, &test_lease[i]); 489 } 490 if (LEASE_NOT_EMPTY(lq)) 491 atf_tc_fail("queue not empty"); 492 493} 494 495ATF_TP_ADD_TCS(tp) 496{ 497 ATF_TP_ADD_TC(tp, leaseq_basic); 498 ATF_TP_ADD_TC(tp, leaseq_add_to_end); 499 ATF_TP_ADD_TC(tp, leaseq_add_to_start); 500 ATF_TP_ADD_TC(tp, leaseq_add_to_middle); 501 ATF_TP_ADD_TC(tp, leaseq_cycle); 502 ATF_TP_ADD_TC(tp, leaseq_long); 503 ATF_TP_ADD_TC(tp, leaseq_same_time); 504 return (atf_no_error()); 505} 506