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 */
47 ATF_TC(leaseq_basic);
ATF_TC_HEAD(leaseq_basic,tc)48 ATF_TC_HEAD(leaseq_basic, tc)
49 {
50 	atf_tc_set_md_var(tc, "descr", "Verify basic functions");
51 }
52 
ATF_TC_BODY(leaseq_basic,tc)53 ATF_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 */
110 ATF_TC(leaseq_add_to_end);
ATF_TC_HEAD(leaseq_add_to_end,tc)111 ATF_TC_HEAD(leaseq_add_to_end, tc)
112 {
113 	atf_tc_set_md_var(tc, "descr", "Verify adding to end of list");
114 }
115 
ATF_TC_BODY(leaseq_add_to_end,tc)116 ATF_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 */
166 ATF_TC(leaseq_add_to_start);
ATF_TC_HEAD(leaseq_add_to_start,tc)167 ATF_TC_HEAD(leaseq_add_to_start, tc)
168 {
169 	atf_tc_set_md_var(tc, "descr", "Verify adding to start of list");
170 }
171 
ATF_TC_BODY(leaseq_add_to_start,tc)172 ATF_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 */
228 ATF_TC(leaseq_add_to_middle);
ATF_TC_HEAD(leaseq_add_to_middle,tc)229 ATF_TC_HEAD(leaseq_add_to_middle, tc)
230 {
231 	atf_tc_set_md_var(tc, "descr", "Verify adding to end of list");
232 }
233 
ATF_TC_BODY(leaseq_add_to_middle,tc)234 ATF_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 */
288 ATF_TC(leaseq_cycle);
ATF_TC_HEAD(leaseq_cycle,tc)289 ATF_TC_HEAD(leaseq_cycle, tc)
290 {
291 	atf_tc_set_md_var(tc, "descr", "Verify cycling the list");
292 }
293 
ATF_TC_BODY(leaseq_cycle,tc)294 ATF_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 
366 ATF_TC(leaseq_long);
ATF_TC_HEAD(leaseq_long,tc)367 ATF_TC_HEAD(leaseq_long, tc)
368 {
369 	atf_tc_set_md_var(tc, "descr", "Verify a long list");
370 }
371 
ATF_TC_BODY(leaseq_long,tc)372 ATF_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  */
432 ATF_TC(leaseq_same_time);
ATF_TC_HEAD(leaseq_same_time,tc)433 ATF_TC_HEAD(leaseq_same_time, tc)
434 {
435 	atf_tc_set_md_var(tc, "descr", "Verify adding leases with same time");
436 }
437 
ATF_TC_BODY(leaseq_same_time,tc)438 ATF_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 
ATF_TP_ADD_TCS(tp)495 ATF_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