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