1 /*	$NetBSD: hash_unittest.c,v 1.1.1.3 2014/07/12 11:58:16 spz Exp $	*/
2 /*
3  * Copyright (c) 2012 by Internet Systems Consortium, Inc. ("ISC")
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  *   Internet Systems Consortium, Inc.
18  *   950 Charter Street
19  *   Redwood City, CA 94063
20  *   <info@isc.org>
21  *   https://www.isc.org/
22  *
23  */
24 
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: hash_unittest.c,v 1.1.1.3 2014/07/12 11:58:16 spz Exp $");
27 
28 #include "config.h"
29 #include <atf-c.h>
30 #include <omapip/omapip_p.h>
31 #include "dhcpd.h"
32 
33 /*
34  * The following structures are kept here for reference only. As hash functions
35  * are somewhat convoluted, they are copied here for the reference. Original
36  * location is specified. Keep in mind that it may change over time:
37  *
38  * copied from server/omapi.c:49 *
39  * omapi_object_type_t *dhcp_type_lease;
40  * omapi_object_type_t *dhcp_type_pool;
41  * omapi_object_type_t *dhcp_type_class;
42  * omapi_object_type_t *dhcp_type_subclass;
43  * omapi_object_type_t *dhcp_type_host;
44  *
45  * copied from server/salloc.c:138
46  * OMAPI_OBJECT_ALLOC (lease, struct lease, dhcp_type_lease)
47  * OMAPI_OBJECT_ALLOC (class, struct class, dhcp_type_class)
48  * OMAPI_OBJECT_ALLOC (subclass, struct class, dhcp_type_subclass)
49  * OMAPI_OBJECT_ALLOC (pool, struct pool, dhcp_type_pool)
50  * OMAPI_OBJECT_ALLOC (host, struct host_decl, dhcp_type_host)
51  *
52  * copied from server/mdb.c:2686
53  * HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t,
54  *                lease_reference, lease_dereference, do_ip4_hash)
55  * HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t,
56  *                lease_reference, lease_dereference, do_id_hash)
57  * HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
58  *                 host_reference, host_dereference, do_string_hash)
59  * HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
60  *                 class_reference, class_dereference, do_string_hash)
61  *
62  * copied from server/mdb.c:46
63  * host_hash_t *host_hw_addr_hash;
64  * host_hash_t *host_uid_hash;
65  * host_hash_t *host_name_hash;
66  * lease_id_hash_t *lease_uid_hash;
67  * lease_ip_hash_t *lease_ip_addr_hash;
68  * lease_id_hash_t *lease_hw_addr_hash;
69  */
70 
71 /**
72  *  @brief sets client-id field in host declaration
73  *
74  *  @param host pointer to host declaration
75  *  @param uid pointer to client-id data
76  *  @param uid_len length of the client-id data
77  *
78  *  @return 1 if successful, 0 otherwise
79  */
80 int lease_set_clientid(struct host_decl *host, const unsigned char *uid, int uid_len) {
81 
82     /* clean-up this mess and set client-identifier in a sane way */
83     int real_len = uid_len;
84     if (uid_len == 0) {
85         real_len = strlen((const char *)uid) + 1;
86     }
87 
88     memset(&host->client_identifier, 0, sizeof(host->client_identifier));
89     host->client_identifier.len = uid_len;
90     if (!buffer_allocate(&host->client_identifier.buffer, real_len, MDL)) {
91         return 0;
92     }
93     host->client_identifier.data = host->client_identifier.buffer->data;
94     memcpy((char *)host->client_identifier.data, uid, real_len);
95 
96     return 1;
97 }
98 
99 /// @brief executes uid hash test for specified client-ids (2 hosts)
100 ///
101 /// Creates two host structures, adds first host to the uid hash,
102 /// then adds second host to the hash, then removes first host,
103 /// then removed the second. Many checks are performed during all
104 /// operations.
105 ///
106 /// @param clientid1 client-id of the first host
107 /// @param clientid1_len client-id1 length (may be 0 for strings)
108 /// @param clientid2 client-id of the second host
109 /// @param clientid2_len client-id2 length (may be 0 for strings)
110 void lease_hash_test_2hosts(unsigned char clientid1[], size_t clientid1_len,
111                             unsigned char clientid2[], size_t clientid2_len) {
112 
113     printf("Checking hash operation for 2 hosts: clientid1-len=%lu"
114            "clientid2-len=%lu\n", (unsigned long) clientid1_len,
115            (unsigned long) clientid2_len);
116 
117     dhcp_db_objects_setup ();
118     dhcp_common_objects_setup ();
119 
120     /* check that there is actually zero hosts in the hash */
121     /* @todo: host_hash_for_each() */
122 
123     struct host_decl *host1 = 0, *host2 = 0;
124     struct host_decl *check = 0;
125 
126     /* === step 1: allocate hosts === */
127     ATF_CHECK_MSG(host_allocate(&host1, MDL) == ISC_R_SUCCESS,
128                   "Failed to allocate host");
129     ATF_CHECK_MSG(host_allocate(&host2, MDL) == ISC_R_SUCCESS,
130                   "Failed to allocate host");
131 
132     ATF_CHECK_MSG(host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL) != 0,
133                   "Unable to create new hash");
134 
135     ATF_CHECK_MSG(buffer_allocate(&host1->client_identifier.buffer,
136                                   clientid1_len, MDL) != 0,
137                   "Can't allocate uid buffer for host1");
138 
139     ATF_CHECK_MSG(buffer_allocate(&host2->client_identifier.buffer,
140                                   clientid2_len, MDL) != 0,
141                   "Can't allocate uid buffer for host2");
142 
143     /* setting up host1->client_identifier is actually not needed */
144     /*
145     ATF_CHECK_MSG(lease_set_clientid(host1, clientid1, actual1_len) != 0,
146                   "Failed to set client-id for host1");
147 
148     ATF_CHECK_MSG(lease_set_clientid(host2, clientid2, actual2_len) != 0,
149                   "Failed to set client-id for host2");
150     */
151 
152     ATF_CHECK_MSG(host1->refcnt == 1, "Invalid refcnt for host1");
153     ATF_CHECK_MSG(host2->refcnt == 1, "Invalid refcnt for host2");
154 
155     /* verify that our hosts are not in the hash yet */
156     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
157                                    clientid1_len, MDL) == 0,
158                    "Host1 is not supposed to be in the uid_hash.");
159 
160     ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");
161 
162     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
163                                    clientid2_len, MDL) == 0,
164                   "Host2 is not supposed to be in the uid_hash.");
165     ATF_CHECK_MSG(!check, "Host2 is not supposed to be in the uid_hash.");
166 
167 
168     /* === step 2: add first host to the hash === */
169     host_hash_add(host_uid_hash, clientid1, clientid1_len, host1, MDL);
170 
171     /* 2 pointers expected: ours (host1) and the one stored in hash */
172     ATF_CHECK_MSG(host1->refcnt == 2, "Invalid refcnt for host1");
173     /* 1 pointer expected: just ours (host2) */
174     ATF_CHECK_MSG(host2->refcnt == 1, "Invalid refcnt for host2");
175 
176     /* verify that host1 is really in the hash and the we can find it */
177     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
178                                    clientid1_len, MDL),
179                   "Host1 was supposed to be in the uid_hash.");
180     ATF_CHECK_MSG(check, "Host1 was supposed to be in the uid_hash.");
181 
182     /* Hey! That's not the host we were looking for! */
183     ATF_CHECK_MSG(check == host1, "Wrong host returned by host_hash_lookup");
184 
185     /* 3 pointers: host1, (stored in hash), check */
186     ATF_CHECK_MSG(host1->refcnt == 3, "Invalid refcnt for host1");
187 
188     /* reference count should be increased because we not have a pointer */
189 
190     host_dereference(&check, MDL); /* we don't need it now */
191 
192     ATF_CHECK_MSG(check == NULL, "check pointer is supposed to be NULL");
193 
194     /* 2 pointers: host1, (stored in hash) */
195     ATF_CHECK_MSG(host1->refcnt == 2, "Invalid refcnt for host1");
196 
197     /* verify that host2 is not in the hash */
198     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
199                                    clientid2_len, MDL) == 0,
200                   "Host2 was not supposed to be in the uid_hash[2].");
201     ATF_CHECK_MSG(check == NULL, "Host2 was not supposed to be in the hash.");
202 
203 
204     /* === step 3: add second hot to the hash === */
205     host_hash_add(host_uid_hash, clientid2, clientid2_len, host2, MDL);
206 
207     /* 2 pointers expected: ours (host1) and the one stored in hash */
208     ATF_CHECK_MSG(host2->refcnt == 2, "Invalid refcnt for host2");
209 
210     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
211                                    clientid2_len, MDL),
212                   "Host2 was supposed to be in the uid_hash.");
213     ATF_CHECK_MSG(check, "Host2 was supposed to be in the uid_hash.");
214 
215     /* Hey! That's not the host we were looking for! */
216     ATF_CHECK_MSG(check == host2, "Wrong host returned by host_hash_lookup");
217 
218     /* 3 pointers: host1, (stored in hash), check */
219     ATF_CHECK_MSG(host2->refcnt == 3, "Invalid refcnt for host1");
220 
221     host_dereference(&check, MDL); /* we don't need it now */
222 
223     /* now we have 2 hosts in the hash */
224 
225     /* verify that host1 is still in the hash and the we can find it */
226     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
227                                    clientid1_len, MDL),
228                   "Host1 was supposed to be in the uid_hash.");
229     ATF_CHECK_MSG(check, "Host1 was supposed to be in the uid_hash.");
230 
231     /* Hey! That's not the host we were looking for! */
232     ATF_CHECK_MSG(check == host1, "Wrong host returned by host_hash_lookup");
233 
234     /* 3 pointers: host1, (stored in hash), check */
235     ATF_CHECK_MSG(host1->refcnt == 3, "Invalid refcnt for host1");
236 
237     host_dereference(&check, MDL); /* we don't need it now */
238 
239 
240     /**
241      * @todo check that there is actually two hosts in the hash.
242      * Use host_hash_for_each() for that.
243      */
244 
245     /* === step 4: remove first host from the hash === */
246 
247     /* delete host from hash */
248     host_hash_delete(host_uid_hash, clientid1, clientid1_len, MDL);
249 
250     ATF_CHECK_MSG(host1->refcnt == 1, "Invalid refcnt for host1");
251     ATF_CHECK_MSG(host2->refcnt == 2, "Invalid refcnt for host2");
252 
253     /* verify that host1 is no longer in the hash */
254     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
255                                    clientid1_len, MDL) == 0,
256                    "Host1 is not supposed to be in the uid_hash.");
257     ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");
258 
259     /* host2 should be still there, though */
260     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
261                                    clientid2_len, MDL),
262                    "Host2 was supposed to still be in the uid_hash.");
263     host_dereference(&check, MDL);
264 
265     /* === step 5: remove second host from the hash === */
266     host_hash_delete(host_uid_hash, clientid2, clientid2_len, MDL);
267 
268     ATF_CHECK_MSG(host1->refcnt == 1, "Invalid refcnt for host1");
269     ATF_CHECK_MSG(host2->refcnt == 1, "Invalid refcnt for host2");
270 
271     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
272                                    clientid2_len, MDL) == 0,
273                    "Host2 was not supposed to be in the uid_hash anymore.");
274 
275     host_dereference(&host1, MDL);
276     host_dereference(&host2, MDL);
277 
278     /*
279      * No easy way to check if the host object were actually released.
280      * We could run it in valgrind and check for memory leaks.
281      */
282 
283 #if defined (DEBUG_MEMORY_LEAKAGE) && defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
284     /* @todo: Should be called in cleanup */
285     free_everything ();
286 #endif
287 }
288 
289 /// @brief executes uid hash test for specified client-ids (3 hosts)
290 ///
291 /// Creates three host structures, adds first host to the uid hash,
292 /// then adds second host to the hash, then removes first host,
293 /// then removed the second. Many checks are performed during all
294 /// operations.
295 ///
296 /// @param clientid1 client-id of the first host
297 /// @param clientid1_len client-id1 length (may be 0 for strings)
298 /// @param clientid2 client-id of the second host
299 /// @param clientid2_len client-id2 length (may be 0 for strings)
300 /// @param clientid3 client-id of the second host
301 /// @param clientid3_len client-id2 length (may be 0 for strings)
302 void lease_hash_test_3hosts(unsigned char clientid1[], size_t clientid1_len,
303                             unsigned char clientid2[], size_t clientid2_len,
304                             unsigned char clientid3[], size_t clientid3_len) {
305 
306     printf("Checking hash operation for 3 hosts: clientid1-len=%lu"
307            " clientid2-len=%lu clientid3-len=%lu\n",
308            (unsigned long) clientid1_len, (unsigned long) clientid2_len,
309            (unsigned long) clientid3_len);
310 
311     dhcp_db_objects_setup ();
312     dhcp_common_objects_setup ();
313 
314     /* check that there is actually zero hosts in the hash */
315     /* @todo: host_hash_for_each() */
316 
317     struct host_decl *host1 = 0, *host2 = 0, *host3 = 0;
318     struct host_decl *check = 0;
319 
320     /* === step 1: allocate hosts === */
321     ATF_CHECK_MSG(host_allocate(&host1, MDL) == ISC_R_SUCCESS,
322                   "Failed to allocate host");
323     ATF_CHECK_MSG(host_allocate(&host2, MDL) == ISC_R_SUCCESS,
324                   "Failed to allocate host");
325     ATF_CHECK_MSG(host_allocate(&host3, MDL) == ISC_R_SUCCESS,
326                   "Failed to allocate host");
327 
328     ATF_CHECK_MSG(host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL) != 0,
329                   "Unable to create new hash");
330 
331     ATF_CHECK_MSG(buffer_allocate(&host1->client_identifier.buffer,
332                                   clientid1_len, MDL) != 0,
333                   "Can't allocate uid buffer for host1");
334     ATF_CHECK_MSG(buffer_allocate(&host2->client_identifier.buffer,
335                                   clientid2_len, MDL) != 0,
336                   "Can't allocate uid buffer for host2");
337     ATF_CHECK_MSG(buffer_allocate(&host3->client_identifier.buffer,
338                                   clientid3_len, MDL) != 0,
339                   "Can't allocate uid buffer for host3");
340 
341     /* verify that our hosts are not in the hash yet */
342     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
343                                    clientid1_len, MDL) == 0,
344                    "Host1 is not supposed to be in the uid_hash.");
345 
346     ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");
347 
348     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
349                                    clientid2_len, MDL) == 0,
350                   "Host2 is not supposed to be in the uid_hash.");
351     ATF_CHECK_MSG(!check, "Host2 is not supposed to be in the uid_hash.");
352 
353     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
354                                    clientid3_len, MDL) == 0,
355                   "Host3 is not supposed to be in the uid_hash.");
356     ATF_CHECK_MSG(!check, "Host3 is not supposed to be in the uid_hash.");
357 
358     /* === step 2: add hosts to the hash === */
359     host_hash_add(host_uid_hash, clientid1, clientid1_len, host1, MDL);
360     host_hash_add(host_uid_hash, clientid2, clientid2_len, host2, MDL);
361     host_hash_add(host_uid_hash, clientid3, clientid3_len, host3, MDL);
362 
363     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
364                                    clientid1_len, MDL),
365                   "Host1 was supposed to be in the uid_hash.");
366     /* Hey! That's not the host we were looking for! */
367     ATF_CHECK_MSG(check == host1, "Wrong host returned by host_hash_lookup");
368     host_dereference(&check, MDL); /* we don't need it now */
369 
370     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
371                                    clientid2_len, MDL),
372                   "Host2 was supposed to be in the uid_hash.");
373     ATF_CHECK_MSG(check, "Host2 was supposed to be in the uid_hash.");
374     /* Hey! That's not the host we were looking for! */
375     ATF_CHECK_MSG(check == host2, "Wrong host returned by host_hash_lookup");
376     host_dereference(&check, MDL); /* we don't need it now */
377 
378     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
379                                    clientid3_len, MDL),
380                   "Host3 was supposed to be in the uid_hash.");
381     ATF_CHECK_MSG(check, "Host3 was supposed to be in the uid_hash.");
382     /* Hey! That's not the host we were looking for! */
383     ATF_CHECK_MSG(check == host3, "Wrong host returned by host_hash_lookup");
384     host_dereference(&check, MDL); /* we don't need it now */
385 
386     /* === step 4: remove first host from the hash === */
387 
388     /* delete host from hash */
389     host_hash_delete(host_uid_hash, clientid1, clientid1_len, MDL);
390 
391     /* verify that host1 is no longer in the hash */
392     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid1,
393                                    clientid1_len, MDL) == 0,
394                    "Host1 is not supposed to be in the uid_hash.");
395     ATF_CHECK_MSG(!check, "Host1 is not supposed to be in the uid_hash.");
396 
397     /* host2 and host3 should be still there, though */
398     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
399                                    clientid2_len, MDL),
400                    "Host2 was supposed to still be in the uid_hash.");
401     host_dereference(&check, MDL);
402     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
403                                    clientid3_len, MDL),
404                    "Host3 was supposed to still be in the uid_hash.");
405     host_dereference(&check, MDL);
406 
407     /* === step 5: remove second host from the hash === */
408     host_hash_delete(host_uid_hash, clientid2, clientid2_len, MDL);
409 
410     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid2,
411                                    clientid2_len, MDL) == 0,
412                    "Host2 was not supposed to be in the uid_hash anymore.");
413     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
414                                    clientid3_len, MDL),
415                    "Host3 was supposed to still be in the uid_hash.");
416     host_dereference(&check, MDL);
417 
418     /* === step 6: remove the last (third) host from the hash === */
419     host_hash_delete(host_uid_hash, clientid3, clientid3_len, MDL);
420 
421     ATF_CHECK_MSG(host_hash_lookup(&check, host_uid_hash, clientid3,
422                                    clientid3_len, MDL) == 0,
423                    "Host3 was not supposed to be in the uid_hash anymore.");
424     host_dereference(&check, MDL);
425 
426 
427     host_dereference(&host1, MDL);
428     host_dereference(&host2, MDL);
429     host_dereference(&host3, MDL);
430 
431     /*
432      * No easy way to check if the host object were actually released.
433      * We could run it in valgrind and check for memory leaks.
434      */
435 
436 #if defined (DEBUG_MEMORY_LEAKAGE) && defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
437     /* @todo: Should be called in cleanup */
438     free_everything ();
439 #endif
440 }
441 
442 ATF_TC(lease_hash_basic_2hosts);
443 
444 ATF_TC_HEAD(lease_hash_basic_2hosts, tc) {
445     atf_tc_set_md_var(tc, "descr", "Basic lease hash tests");
446     /*
447      * The following functions are tested:
448      * host_allocate(), host_new_hash(), buffer_allocate(), host_hash_lookup()
449      * host_hash_add(), host_hash_delete()
450      */
451 }
452 
453 ATF_TC_BODY(lease_hash_basic_2hosts, tc) {
454 
455     unsigned char clientid1[] = { 0x1, 0x2, 0x3 };
456     unsigned char clientid2[] = { 0xff, 0xfe };
457 
458     lease_hash_test_2hosts(clientid1, sizeof(clientid1),
459                            clientid2, sizeof(clientid2));
460 }
461 
462 
463 ATF_TC(lease_hash_string_2hosts);
464 
465 ATF_TC_HEAD(lease_hash_string_2hosts, tc) {
466     atf_tc_set_md_var(tc, "descr", "string-based lease hash tests");
467     /*
468      * The following functions are tested:
469      * host_allocate(), host_new_hash(), buffer_allocate(), host_hash_lookup()
470      * host_hash_add(), host_hash_delete()
471      */
472 }
473 
474 ATF_TC_BODY(lease_hash_string_2hosts, tc) {
475 
476     unsigned char clientid1[] = "Alice";
477     unsigned char clientid2[] = "Bob";
478 
479     lease_hash_test_2hosts(clientid1, 0, clientid2, 0);
480 }
481 
482 
483 ATF_TC(lease_hash_negative1);
484 
485 ATF_TC_HEAD(lease_hash_negative1, tc) {
486     atf_tc_set_md_var(tc, "descr", "Negative tests for lease hash");
487 }
488 
489 ATF_TC_BODY(lease_hash_negative1, tc) {
490 
491     unsigned char clientid1[] = { 0x1 };
492     unsigned char clientid2[] = { 0x0 };
493 
494     lease_hash_test_2hosts(clientid1, 0, clientid2, 1);
495 }
496 
497 
498 
499 ATF_TC(lease_hash_string_3hosts);
500 ATF_TC_HEAD(lease_hash_string_3hosts, tc) {
501     atf_tc_set_md_var(tc, "descr", "string-based lease hash tests");
502     /*
503      * The following functions are tested:
504      * host_allocate(), host_new_hash(), buffer_allocate(), host_hash_lookup()
505      * host_hash_add(), host_hash_delete()
506      */
507 }
508 ATF_TC_BODY(lease_hash_string_3hosts, tc) {
509 
510     unsigned char clientid1[] = "Alice";
511     unsigned char clientid2[] = "Bob";
512     unsigned char clientid3[] = "Charlie";
513 
514     lease_hash_test_3hosts(clientid1, 0, clientid2, 0, clientid3, 0);
515 }
516 
517 
518 ATF_TC(lease_hash_basic_3hosts);
519 ATF_TC_HEAD(lease_hash_basic_3hosts, tc) {
520     atf_tc_set_md_var(tc, "descr", "Basic lease hash tests");
521     /*
522      * The following functions are tested:
523      * host_allocate(), host_new_hash(), buffer_allocate(), host_hash_lookup()
524      * host_hash_add(), host_hash_delete()
525      */
526 }
527 ATF_TC_BODY(lease_hash_basic_3hosts, tc) {
528 
529     unsigned char clientid1[] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9 };
530     unsigned char clientid2[] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 };
531     unsigned char clientid3[] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 };
532 
533     lease_hash_test_3hosts(clientid1, sizeof(clientid1),
534                            clientid2, sizeof(clientid2),
535                            clientid3, sizeof(clientid3));
536 }
537 
538 #if 0
539 /* This test is disabled as we solved the issue by prohibiting
540    the code from using an improper client id earlier and restoring
541    the hash code to its previous state.  As we may choose to
542    redo the hash code again this test hasn't been deleted.
543 */
544 /* this test is a direct reproduction of 29851 issue */
545 ATF_TC(uid_hash_rt29851);
546 
547 ATF_TC_HEAD(uid_hash_rt29851, tc) {
548     atf_tc_set_md_var(tc, "descr", "Uid hash tests");
549 
550     /*
551      * this test should last less than millisecond. If its execution
552      *  is longer than 3 second, we hit infinite loop.
553      */
554     atf_tc_set_md_var(tc, "timeout", "3");
555 }
556 
557 ATF_TC_BODY(uid_hash_rt29851, tc) {
558 
559     unsigned char clientid1[] = { 0x0 };
560     unsigned char clientid2[] = { 0x0 };
561     unsigned char clientid3[] = { 0x0 };
562 
563     int clientid1_len = 1;
564     int clientid2_len = 1;
565     int clientid3_len = 0;
566 
567     struct lease *lease1 = 0, *lease2 = 0, *lease3 = 0;
568 
569     dhcp_db_objects_setup ();
570     dhcp_common_objects_setup ();
571 
572     ATF_CHECK(lease_id_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL));
573 
574     ATF_CHECK(lease_allocate (&lease1, MDL) == ISC_R_SUCCESS);
575     ATF_CHECK(lease_allocate (&lease2, MDL) == ISC_R_SUCCESS);
576     ATF_CHECK(lease_allocate (&lease3, MDL) == ISC_R_SUCCESS);
577 
578     lease1->uid = clientid1;
579     lease2->uid = clientid2;
580     lease3->uid = clientid3;
581 
582     lease1->uid_len = clientid1_len;
583     lease2->uid_len = clientid2_len;
584     lease3->uid_len = clientid3_len;
585 
586     uid_hash_add(lease1);
587     /* uid_hash_delete(lease2); // not necessary for actual issue repro */
588     uid_hash_add(lease3);
589 
590     /* lease2->uid_len = 0;     // not necessary for actual issue repro */
591     /* uid_hash_delete(lease2); // not necessary for actual issue repro */
592     /* uid_hash_delete(lease3); // not necessary for actual issue repro */
593     uid_hash_delete(lease1);
594 
595     /* lease2->uid_len = 1;     // not necessary for actual issue repro */
596     uid_hash_add(lease1);
597     uid_hash_delete(lease2);
598 }
599 #endif
600 
601 ATF_TP_ADD_TCS(tp) {
602     ATF_TP_ADD_TC(tp, lease_hash_basic_2hosts);
603     ATF_TP_ADD_TC(tp, lease_hash_basic_3hosts);
604     ATF_TP_ADD_TC(tp, lease_hash_string_2hosts);
605     ATF_TP_ADD_TC(tp, lease_hash_string_3hosts);
606     ATF_TP_ADD_TC(tp, lease_hash_negative1);
607 #if 0 /* see comment in function */
608     ATF_TP_ADD_TC(tp, uid_hash_rt29851);
609 #endif
610     return (atf_no_error());
611 }
612