Home | History | Annotate | Line # | Download | only in test
      1      1.1  christos /*
      2  1.1.1.2  christos  * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  * Copyright (c) 2017, Oracle and/or its affiliates.  All rights reserved.
      4      1.1  christos  *
      5  1.1.1.2  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      6      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      7      1.1  christos  * in the file LICENSE in the source distribution or at
      8      1.1  christos  * https://www.openssl.org/source/license.html
      9      1.1  christos  */
     10      1.1  christos 
     11      1.1  christos #include <stdio.h>
     12      1.1  christos #include <string.h>
     13      1.1  christos 
     14      1.1  christos #include <openssl/opensslconf.h>
     15      1.1  christos #include <openssl/lhash.h>
     16      1.1  christos #include <openssl/err.h>
     17      1.1  christos #include <openssl/crypto.h>
     18      1.1  christos 
     19      1.1  christos #include "internal/nelem.h"
     20      1.1  christos #include "testutil.h"
     21      1.1  christos 
     22      1.1  christos /*
     23      1.1  christos  * The macros below generate unused functions which error out one of the clang
     24      1.1  christos  * builds.  We disable this check here.
     25      1.1  christos  */
     26      1.1  christos #ifdef __clang__
     27      1.1  christos #pragma clang diagnostic ignored "-Wunused-function"
     28      1.1  christos #endif
     29      1.1  christos 
     30      1.1  christos DEFINE_LHASH_OF(int);
     31      1.1  christos 
     32      1.1  christos static int int_tests[] = { 65537, 13, 1, 3, -5, 6, 7, 4, -10, -12, -14, 22, 9,
     33      1.1  christos                            -17, 16, 17, -23, 35, 37, 173, 11 };
     34      1.1  christos static const unsigned int n_int_tests = OSSL_NELEM(int_tests);
     35      1.1  christos static short int_found[OSSL_NELEM(int_tests)];
     36  1.1.1.2  christos static short int_not_found;
     37      1.1  christos 
     38      1.1  christos static unsigned long int int_hash(const int *p)
     39      1.1  christos {
     40      1.1  christos     return 3 & *p;      /* To force collisions */
     41      1.1  christos }
     42      1.1  christos 
     43      1.1  christos static int int_cmp(const int *p, const int *q)
     44      1.1  christos {
     45      1.1  christos     return *p != *q;
     46      1.1  christos }
     47      1.1  christos 
     48      1.1  christos static int int_find(int n)
     49      1.1  christos {
     50      1.1  christos     unsigned int i;
     51      1.1  christos 
     52      1.1  christos     for (i = 0; i < n_int_tests; i++)
     53      1.1  christos         if (int_tests[i] == n)
     54      1.1  christos             return i;
     55      1.1  christos     return -1;
     56      1.1  christos }
     57      1.1  christos 
     58      1.1  christos static void int_doall(int *v)
     59      1.1  christos {
     60  1.1.1.2  christos     const int n = int_find(*v);
     61  1.1.1.2  christos 
     62  1.1.1.2  christos     if (n < 0)
     63  1.1.1.2  christos         int_not_found++;
     64  1.1.1.2  christos     else
     65  1.1.1.2  christos         int_found[n]++;
     66      1.1  christos }
     67      1.1  christos 
     68      1.1  christos static void int_doall_arg(int *p, short *f)
     69      1.1  christos {
     70  1.1.1.2  christos     const int n = int_find(*p);
     71  1.1.1.2  christos 
     72  1.1.1.2  christos     if (n < 0)
     73  1.1.1.2  christos         int_not_found++;
     74  1.1.1.2  christos     else
     75  1.1.1.2  christos         f[n]++;
     76      1.1  christos }
     77      1.1  christos 
     78      1.1  christos IMPLEMENT_LHASH_DOALL_ARG(int, short);
     79      1.1  christos 
     80      1.1  christos static int test_int_lhash(void)
     81      1.1  christos {
     82      1.1  christos     static struct {
     83      1.1  christos         int data;
     84      1.1  christos         int null;
     85      1.1  christos     } dels[] = {
     86      1.1  christos         { 65537,    0 },
     87      1.1  christos         { 173,      0 },
     88      1.1  christos         { 999,      1 },
     89      1.1  christos         { 37,       0 },
     90      1.1  christos         { 1,        0 },
     91      1.1  christos         { 34,       1 }
     92      1.1  christos     };
     93      1.1  christos     const unsigned int n_dels = OSSL_NELEM(dels);
     94      1.1  christos     LHASH_OF(int) *h = lh_int_new(&int_hash, &int_cmp);
     95      1.1  christos     unsigned int i;
     96      1.1  christos     int testresult = 0, j, *p;
     97      1.1  christos 
     98      1.1  christos     if (!TEST_ptr(h))
     99      1.1  christos         goto end;
    100      1.1  christos 
    101      1.1  christos     /* insert */
    102      1.1  christos     for (i = 0; i < n_int_tests; i++)
    103      1.1  christos         if (!TEST_ptr_null(lh_int_insert(h, int_tests + i))) {
    104      1.1  christos             TEST_info("int insert %d", i);
    105      1.1  christos             goto end;
    106      1.1  christos         }
    107      1.1  christos 
    108      1.1  christos     /* num_items */
    109      1.1  christos     if (!TEST_int_eq(lh_int_num_items(h), n_int_tests))
    110      1.1  christos         goto end;
    111      1.1  christos 
    112      1.1  christos     /* retrieve */
    113      1.1  christos     for (i = 0; i < n_int_tests; i++)
    114      1.1  christos         if (!TEST_int_eq(*lh_int_retrieve(h, int_tests + i), int_tests[i])) {
    115      1.1  christos             TEST_info("lhash int retrieve value %d", i);
    116      1.1  christos             goto end;
    117      1.1  christos         }
    118      1.1  christos     for (i = 0; i < n_int_tests; i++)
    119      1.1  christos         if (!TEST_ptr_eq(lh_int_retrieve(h, int_tests + i), int_tests + i)) {
    120      1.1  christos             TEST_info("lhash int retrieve address %d", i);
    121      1.1  christos             goto end;
    122      1.1  christos         }
    123      1.1  christos     j = 1;
    124      1.1  christos     if (!TEST_ptr_eq(lh_int_retrieve(h, &j), int_tests + 2))
    125      1.1  christos         goto end;
    126      1.1  christos 
    127      1.1  christos     /* replace */
    128      1.1  christos     j = 13;
    129      1.1  christos     if (!TEST_ptr(p = lh_int_insert(h, &j)))
    130      1.1  christos         goto end;
    131      1.1  christos     if (!TEST_ptr_eq(p, int_tests + 1))
    132      1.1  christos         goto end;
    133      1.1  christos     if (!TEST_ptr_eq(lh_int_retrieve(h, int_tests + 1), &j))
    134      1.1  christos         goto end;
    135      1.1  christos 
    136      1.1  christos     /* do_all */
    137      1.1  christos     memset(int_found, 0, sizeof(int_found));
    138  1.1.1.2  christos     int_not_found = 0;
    139      1.1  christos     lh_int_doall(h, &int_doall);
    140  1.1.1.2  christos     if (!TEST_int_eq(int_not_found, 0)) {
    141  1.1.1.2  christos         TEST_info("lhash int doall encountered a not found condition");
    142  1.1.1.2  christos         goto end;
    143  1.1.1.2  christos     }
    144      1.1  christos     for (i = 0; i < n_int_tests; i++)
    145      1.1  christos         if (!TEST_int_eq(int_found[i], 1)) {
    146      1.1  christos             TEST_info("lhash int doall %d", i);
    147      1.1  christos             goto end;
    148      1.1  christos         }
    149      1.1  christos 
    150      1.1  christos     /* do_all_arg */
    151      1.1  christos     memset(int_found, 0, sizeof(int_found));
    152  1.1.1.2  christos     int_not_found = 0;
    153      1.1  christos     lh_int_doall_short(h, int_doall_arg, int_found);
    154  1.1.1.2  christos     if (!TEST_int_eq(int_not_found, 0)) {
    155  1.1.1.2  christos         TEST_info("lhash int doall arg encountered a not found condition");
    156  1.1.1.2  christos         goto end;
    157  1.1.1.2  christos     }
    158      1.1  christos     for (i = 0; i < n_int_tests; i++)
    159      1.1  christos         if (!TEST_int_eq(int_found[i], 1)) {
    160      1.1  christos             TEST_info("lhash int doall arg %d", i);
    161      1.1  christos             goto end;
    162      1.1  christos         }
    163      1.1  christos 
    164      1.1  christos     /* delete */
    165      1.1  christos     for (i = 0; i < n_dels; i++) {
    166      1.1  christos         const int b = lh_int_delete(h, &dels[i].data) == NULL;
    167      1.1  christos         if (!TEST_int_eq(b ^ dels[i].null,  0)) {
    168      1.1  christos             TEST_info("lhash int delete %d", i);
    169      1.1  christos             goto end;
    170      1.1  christos         }
    171      1.1  christos     }
    172      1.1  christos 
    173      1.1  christos     /* error */
    174      1.1  christos     if (!TEST_int_eq(lh_int_error(h), 0))
    175      1.1  christos         goto end;
    176      1.1  christos 
    177      1.1  christos     testresult = 1;
    178      1.1  christos end:
    179      1.1  christos     lh_int_free(h);
    180      1.1  christos     return testresult;
    181      1.1  christos }
    182      1.1  christos 
    183      1.1  christos static unsigned long int stress_hash(const int *p)
    184      1.1  christos {
    185      1.1  christos     return *p;
    186      1.1  christos }
    187      1.1  christos 
    188      1.1  christos static int test_stress(void)
    189      1.1  christos {
    190      1.1  christos     LHASH_OF(int) *h = lh_int_new(&stress_hash, &int_cmp);
    191      1.1  christos     const unsigned int n = 2500000;
    192      1.1  christos     unsigned int i;
    193      1.1  christos     int testresult = 0, *p;
    194      1.1  christos 
    195      1.1  christos     if (!TEST_ptr(h))
    196      1.1  christos         goto end;
    197      1.1  christos 
    198      1.1  christos     /* insert */
    199      1.1  christos     for (i = 0; i < n; i++) {
    200      1.1  christos         p = OPENSSL_malloc(sizeof(i));
    201      1.1  christos         if (!TEST_ptr(p)) {
    202      1.1  christos             TEST_info("lhash stress out of memory %d", i);
    203      1.1  christos             goto end;
    204      1.1  christos         }
    205      1.1  christos         *p = 3 * i + 1;
    206      1.1  christos         lh_int_insert(h, p);
    207      1.1  christos     }
    208      1.1  christos 
    209      1.1  christos     /* num_items */
    210      1.1  christos     if (!TEST_int_eq(lh_int_num_items(h), n))
    211      1.1  christos             goto end;
    212      1.1  christos 
    213      1.1  christos     TEST_info("hash full statistics:");
    214      1.1  christos     OPENSSL_LH_stats_bio((OPENSSL_LHASH *)h, bio_err);
    215      1.1  christos     TEST_note("hash full node usage:");
    216      1.1  christos     OPENSSL_LH_node_usage_stats_bio((OPENSSL_LHASH *)h, bio_err);
    217      1.1  christos 
    218      1.1  christos     /* delete in a different order */
    219      1.1  christos     for (i = 0; i < n; i++) {
    220      1.1  christos         const int j = (7 * i + 4) % n * 3 + 1;
    221      1.1  christos 
    222      1.1  christos         if (!TEST_ptr(p = lh_int_delete(h, &j))) {
    223      1.1  christos             TEST_info("lhash stress delete %d\n", i);
    224      1.1  christos             goto end;
    225      1.1  christos         }
    226      1.1  christos         if (!TEST_int_eq(*p, j)) {
    227      1.1  christos             TEST_info("lhash stress bad value %d", i);
    228      1.1  christos             goto end;
    229      1.1  christos         }
    230      1.1  christos         OPENSSL_free(p);
    231      1.1  christos     }
    232      1.1  christos 
    233      1.1  christos     TEST_info("hash empty statistics:");
    234      1.1  christos     OPENSSL_LH_stats_bio((OPENSSL_LHASH *)h, bio_err);
    235      1.1  christos     TEST_note("hash empty node usage:");
    236      1.1  christos     OPENSSL_LH_node_usage_stats_bio((OPENSSL_LHASH *)h, bio_err);
    237      1.1  christos 
    238      1.1  christos     testresult = 1;
    239      1.1  christos end:
    240      1.1  christos     lh_int_free(h);
    241      1.1  christos     return testresult;
    242      1.1  christos }
    243      1.1  christos 
    244      1.1  christos int setup_tests(void)
    245      1.1  christos {
    246      1.1  christos     ADD_TEST(test_int_lhash);
    247      1.1  christos     ADD_TEST(test_stress);
    248      1.1  christos     return 1;
    249      1.1  christos }
    250