/* * Copyright (C) 2015-2017 by Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include #include "dhcpd.h" #include /* * Test the lease queue code. These tests will verify that we can * add, find and remove leases from the lease queue code * * Thoughout the tests * lq will be the lease queue for which we add or removing leases * test_leaseX will be the leases we add or remove * We only care about the sort_time in the lease structure for these * tests but need to do a lease_reference in order to keep the ref * count positive to avoid the omapi code trying to free the object. * We can't use lease_allocate easily as we haven't set up the omapi * object information in the test. */ #if defined (BINARY_LEASES) #define INIT_LQ(LQ) memset(&(LQ), 0, sizeof(struct leasechain)) #else #define INIT_LQ(LQ) lq = NULL #endif /* Test basic leaseq functions with a single lease */ /*- empty, add, get, and remove */ ATF_TC(leaseq_basic); ATF_TC_HEAD(leaseq_basic, tc) { atf_tc_set_md_var(tc, "descr", "Verify basic functions"); } ATF_TC_BODY(leaseq_basic, tc) { LEASE_STRUCT lq; struct lease test_lease1, *check_lease; INIT_LQ(lq); memset(&test_lease1, 0, sizeof(struct lease)); test_lease1.sort_time = 10; check_lease = NULL; lease_reference(&check_lease, &test_lease1, MDL); /* Check that the lq is empty */ if ((LEASE_NOT_EMPTY(lq)) || (LEASE_NOT_EMPTYP(&lq))) atf_tc_fail("lq not empty at start."); /* And that getting the first lease is okay when queue is empty */ if ((LEASE_GET_FIRST(lq) != NULL) || (LEASE_GET_FIRSTP(&lq) != NULL)) atf_tc_fail("lease not null"); /* Add a lease */ LEASE_INSERTP(&lq, &test_lease1); /* lq shouldn't be empty anymore */ if (!(LEASE_NOT_EMPTY(lq)) || !(LEASE_NOT_EMPTYP(&lq))) atf_tc_fail("lq empty after insertion."); /* We should have the same lease we inserted */ check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease1) atf_tc_fail("leases don't match"); /* We should have the same lease we inserted */ check_lease = LEASE_GET_FIRSTP(&lq); if (check_lease != &test_lease1) atf_tc_fail("leases don't match"); /* Check that doing a get on the last lease returns NULL */ if ((LEASE_GET_NEXT(lq, check_lease) != NULL) || (LEASE_GET_NEXTP(&lq, check_lease) != NULL)) { atf_tc_fail("Next not null"); } /* Remove the lease */ LEASE_REMOVEP(&lq, &test_lease1); /* and verify the lease queue is empty again */ if ((LEASE_NOT_EMPTY(lq)) || (LEASE_NOT_EMPTYP(&lq))) atf_tc_fail("lq not empty afer removal"); /* And that getting the first lease is okay when queue is empty */ if ((LEASE_GET_FIRST(lq) != NULL) || (LEASE_GET_FIRSTP(&lq) != NULL)) atf_tc_fail("lease not null"); } /* Test if we can add leases to the end of the list and remove them * from the end */ ATF_TC(leaseq_add_to_end); ATF_TC_HEAD(leaseq_add_to_end, tc) { atf_tc_set_md_var(tc, "descr", "Verify adding to end of list"); } ATF_TC_BODY(leaseq_add_to_end, tc) { LEASE_STRUCT lq; struct lease test_lease[3], *check_lease; int i; INIT_LQ(lq); /* create and add 3 leases */ for (i = 0; i < 3; i++) { memset(&test_lease[i], 0, sizeof(struct lease)); test_lease[i].sort_time = i; check_lease = NULL; lease_reference(&check_lease, &test_lease[i], MDL); LEASE_INSERTP(&lq, &test_lease[i]); } /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); for (i = 0; i < 3; i++) { if (check_lease != &test_lease[i]) atf_tc_fail("leases don't match, %d", i); check_lease = LEASE_GET_NEXT(lq, check_lease); } if (check_lease != NULL) atf_tc_fail("lease not null"); /* Remove the last lease and check the list */ LEASE_REMOVEP(&lq, &test_lease[2]); check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[0]) atf_tc_fail("wrong lease after remove, 1"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[1]) atf_tc_fail("wrong lease after remove, 2"); LEASE_REMOVEP(&lq, &test_lease[1]); check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[0]) atf_tc_fail("wrong lease after remove, 3"); LEASE_REMOVEP(&lq, check_lease); /* The lease queue should now be empty */ if (LEASE_NOT_EMPTY(lq)) atf_tc_fail("lq not empty afer removal"); } /* Test if we can add leases to the start of the list and remove them * from the start */ ATF_TC(leaseq_add_to_start); ATF_TC_HEAD(leaseq_add_to_start, tc) { atf_tc_set_md_var(tc, "descr", "Verify adding to start of list"); } ATF_TC_BODY(leaseq_add_to_start, tc) { LEASE_STRUCT lq; struct lease test_lease[3], *check_lease; int i; INIT_LQ(lq); /* create 3 leases */ for (i = 0; i < 3; i++) { memset(&test_lease[i], 0, sizeof(struct lease)); test_lease[i].sort_time = i; check_lease = NULL; lease_reference(&check_lease, &test_lease[i], MDL); } /* Add leases */ LEASE_INSERTP(&lq, &test_lease[2]); LEASE_INSERTP(&lq, &test_lease[1]); LEASE_INSERTP(&lq, &test_lease[0]); /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); for (i = 0; i < 3; i++) { if (check_lease != &test_lease[i]) atf_tc_fail("leases don't match, %d", i); check_lease = LEASE_GET_NEXT(lq, check_lease); } if (check_lease != NULL) atf_tc_fail("lease not null"); /* Remove the first lease and check the next one */ check_lease = LEASE_GET_FIRST(lq); LEASE_REMOVEP(&lq, check_lease); check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[1]) atf_tc_fail("wrong lease after remove, 1"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[2]) atf_tc_fail("wrong lease after remove, 2"); check_lease = LEASE_GET_FIRST(lq); LEASE_REMOVEP(&lq, check_lease); check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[2]) atf_tc_fail("wrong lease after remove, 3"); LEASE_REMOVEP(&lq, check_lease); /* The lease queue should now be empty */ if (LEASE_NOT_EMPTY(lq)) atf_tc_fail("lq not empty afer removal"); } /* Test if we can add leases to the middle of the list and remove them * from the middle */ ATF_TC(leaseq_add_to_middle); ATF_TC_HEAD(leaseq_add_to_middle, tc) { atf_tc_set_md_var(tc, "descr", "Verify adding to end of list"); } ATF_TC_BODY(leaseq_add_to_middle, tc) { LEASE_STRUCT lq; struct lease test_lease[3], *check_lease; int i; INIT_LQ(lq); /* create 3 leases */ for (i = 0; i < 3; i++) { memset(&test_lease[i], 0, sizeof(struct lease)); test_lease[i].sort_time = i; check_lease = NULL; lease_reference(&check_lease, &test_lease[i], MDL); } /* Add leases */ LEASE_INSERTP(&lq, &test_lease[0]); LEASE_INSERTP(&lq, &test_lease[2]); LEASE_INSERTP(&lq, &test_lease[1]); /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); for (i = 0; i < 3; i++) { if (check_lease != &test_lease[i]) atf_tc_fail("leases don't match, %d", i); check_lease = LEASE_GET_NEXT(lq, check_lease); } if (check_lease != NULL) atf_tc_fail("lease not null"); /* Remove the middle lease and check the list */ LEASE_REMOVEP(&lq, &test_lease[1]); check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[0]) atf_tc_fail("wrong lease after remove, 1"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[2]) atf_tc_fail("wrong lease after remove, 2"); LEASE_REMOVEP(&lq, &test_lease[0]); check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[2]) atf_tc_fail("wrong lease after remove, 3"); LEASE_REMOVEP(&lq, check_lease); /* The lease queue should now be empty */ if (LEASE_NOT_EMPTY(lq)) atf_tc_fail("lq not empty afer removal"); } /* Test if we can cycle the leases we add three leases then remove * the first one, update it's sort time and re add it */ ATF_TC(leaseq_cycle); ATF_TC_HEAD(leaseq_cycle, tc) { atf_tc_set_md_var(tc, "descr", "Verify cycling the list"); } ATF_TC_BODY(leaseq_cycle, tc) { LEASE_STRUCT lq; struct lease test_lease[3], *check_lease; int i; INIT_LQ(lq); /* create and add 3 leases */ for (i = 0; i < 3; i++) { memset(&test_lease[i], 0, sizeof(struct lease)); test_lease[i].sort_time = i; check_lease = NULL; lease_reference(&check_lease, &test_lease[i], MDL); LEASE_INSERTP(&lq, &test_lease[i]); } /* Remove first lease, update it and re-insert it */ LEASE_REMOVEP(&lq, &test_lease[0]); test_lease[0].sort_time = 4; LEASE_INSERTP(&lq, &test_lease[0]); /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[1]) atf_tc_fail("leases don't match, 1"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[2]) atf_tc_fail("leases don't match, 2"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[0]) atf_tc_fail("leases don't match, 3"); /* Remove first lease, update it and re-insert it */ LEASE_REMOVEP(&lq, &test_lease[1]); test_lease[1].sort_time = 5; LEASE_INSERTP(&lq, &test_lease[1]); /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[2]) atf_tc_fail("leases don't match, 4"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[0]) atf_tc_fail("leases don't match, 5"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[1]) atf_tc_fail("leases don't match, 6"); /* Remove first lease, update it and re-insert it */ LEASE_REMOVEP(&lq, &test_lease[2]); test_lease[2].sort_time = 6; LEASE_INSERTP(&lq, &test_lease[2]); /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); if (check_lease != &test_lease[0]) atf_tc_fail("leases don't match, 7"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[1]) atf_tc_fail("leases don't match, 8"); check_lease = LEASE_GET_NEXT(lq, check_lease); if (check_lease != &test_lease[2]) atf_tc_fail("leases don't match, 9"); } /* Test what happens if we set the growth factor to a smallish number * and add enough leases to require it to grow multiple times * Mostly this is for the binary leases case but we can most of the * test for both. */ ATF_TC(leaseq_long); ATF_TC_HEAD(leaseq_long, tc) { atf_tc_set_md_var(tc, "descr", "Verify a long list"); } ATF_TC_BODY(leaseq_long, tc) { LEASE_STRUCT lq; struct lease test_lease[20], *check_lease; int i; INIT_LQ(lq); #if defined (BINARY_LEASES) lc_init_growth(&lq, 5); #endif /* create and add 10 leases */ for (i = 0; i < 10; i++) { memset(&test_lease[i], 0, sizeof(struct lease)); test_lease[i].sort_time = i; check_lease = NULL; lease_reference(&check_lease, &test_lease[i], MDL); LEASE_INSERTP(&lq, &test_lease[i]); } /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); for (i = 0; i < 10; i++) { if (check_lease != &test_lease[i]) atf_tc_fail("leases don't match, %d", i); check_lease = LEASE_GET_NEXT(lq, check_lease); } /* Remove first 5 */ for (i = 0; i < 5; i++) { LEASE_REMOVEP(&lq, &test_lease[i]); } /* Add 10 more */ for (i = 10; i < 20; i++) { memset(&test_lease[i], 0, sizeof(struct lease)); test_lease[i].sort_time = i; check_lease = NULL; lease_reference(&check_lease, &test_lease[i], MDL); LEASE_INSERTP(&lq, &test_lease[i]); } /* and the first 5 */ for (i = 0; i < 5; i++) { LEASE_INSERTP(&lq, &test_lease[i]); } /* and check them all out */ check_lease = LEASE_GET_FIRST(lq); for (i = 0; i < 20; i++) { if (check_lease != &test_lease[i]) atf_tc_fail("leases don't match, %d", i); check_lease = LEASE_GET_NEXT(lq, check_lease); } } /* Test if we can add leases that all have the same sort time */ ATF_TC(leaseq_same_time); ATF_TC_HEAD(leaseq_same_time, tc) { atf_tc_set_md_var(tc, "descr", "Verify adding leases with same time"); } ATF_TC_BODY(leaseq_same_time, tc) { LEASE_STRUCT lq; struct lease test_lease[20], *check_lease; int i; INIT_LQ(lq); /* create and add 20 leases */ for (i = 0; i < 20; i++) { memset(&test_lease[i], 0, sizeof(struct lease)); if (i < 10) test_lease[i].sort_time = 10; else test_lease[i].sort_time = 20; check_lease = NULL; lease_reference(&check_lease, &test_lease[i], MDL); LEASE_INSERTP(&lq, &test_lease[i]); } #if defined (BINARY_LEASES) /* the ordering isn't well defined for either but we check * to see what happens in the binary case. At the start * the leases should stay in the order they were added. */ /* check ordering of leases */ check_lease = LEASE_GET_FIRST(lq); for (i = 0; i < 20; i++) { if (check_lease != &test_lease[i]) atf_tc_fail("leases don't match 1, %d", i); check_lease = LEASE_GET_NEXT(lq, check_lease); } if (check_lease != NULL) atf_tc_fail("lease not null"); #endif /* Remove first 10, update their time, but still before * the previous 10 and re add them */ for (i = 0; i < 10; i++) { LEASE_REMOVEP(&lq, &test_lease[i]); test_lease[i].sort_time = 15; LEASE_INSERTP(&lq, &test_lease[i]); } /* The ordering becomes random at this point so we don't * check it. We try to remove them all and see that * we got to an empty queue. */ for (i = 0; i < 20; i++) { LEASE_REMOVEP(&lq, &test_lease[i]); } if (LEASE_NOT_EMPTY(lq)) atf_tc_fail("queue not empty"); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, leaseq_basic); ATF_TP_ADD_TC(tp, leaseq_add_to_end); ATF_TP_ADD_TC(tp, leaseq_add_to_start); ATF_TP_ADD_TC(tp, leaseq_add_to_middle); ATF_TP_ADD_TC(tp, leaseq_cycle); ATF_TP_ADD_TC(tp, leaseq_long); ATF_TP_ADD_TC(tp, leaseq_same_time); return (atf_no_error()); }