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