Home | History | Annotate | Download | only in lhash
      1 /* Copyright (c) 2014, Google Inc.
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     14 
     15 #define _BSD_SOURCE
     16 
     17 #include <openssl/crypto.h>
     18 #include <openssl/lhash.h>
     19 
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 
     24 struct dummy_lhash_node {
     25   char *s;
     26   struct dummy_lhash_node *next;
     27 };
     28 
     29 struct dummy_lhash {
     30   struct dummy_lhash_node *head;
     31 };
     32 
     33 static void dummy_lh_free(struct dummy_lhash *lh) {
     34   struct dummy_lhash_node *cur, *next;
     35 
     36   for (cur = lh->head; cur != NULL; cur = next) {
     37     next = cur->next;
     38     free(cur->s);
     39     free(cur);
     40   }
     41 }
     42 
     43 static size_t dummy_lh_num_items(const struct dummy_lhash *lh) {
     44   size_t count = 0;
     45   struct dummy_lhash_node *cur;
     46 
     47   for (cur = lh->head; cur != NULL; cur = cur->next) {
     48     count++;
     49   }
     50 
     51   return count;
     52 }
     53 
     54 static char *dummy_lh_retrieve(struct dummy_lhash *lh, const char *s) {
     55   struct dummy_lhash_node *cur;
     56 
     57   for (cur = lh->head; cur != NULL; cur = cur->next) {
     58     if (strcmp(cur->s, s) == 0) {
     59       return cur->s;
     60     }
     61   }
     62 
     63   return NULL;
     64 }
     65 
     66 static int dummy_lh_insert(struct dummy_lhash *lh, char **old_data, char *s) {
     67   struct dummy_lhash_node *node, *cur;
     68 
     69   for (cur = lh->head; cur != NULL; cur = cur->next) {
     70     if (strcmp(cur->s, s) == 0) {
     71       *old_data = cur->s;
     72       cur->s = s;
     73       return 1;
     74     }
     75   }
     76 
     77   node = malloc(sizeof(struct dummy_lhash_node));
     78   *old_data = NULL;
     79   node->s = s;
     80   node->next = lh->head;
     81   lh->head = node;
     82   return 1;
     83 }
     84 
     85 static char *dummy_lh_delete(struct dummy_lhash *lh, const void *s) {
     86   struct dummy_lhash_node *cur, **next_ptr;
     87   char *ret;
     88 
     89   next_ptr = &lh->head;
     90   for (cur = lh->head; cur != NULL; cur = cur->next) {
     91     if (strcmp(cur->s, s) == 0) {
     92       ret = cur->s;
     93       *next_ptr = cur->next;
     94       free(cur);
     95       return ret;
     96     }
     97     next_ptr = &cur->next;
     98   }
     99 
    100   return NULL;
    101 }
    102 
    103 static char *rand_string(void) {
    104   unsigned len = 1 + (rand() % 3);
    105   char *ret = malloc(len + 1);
    106   unsigned i;
    107 
    108   for (i = 0; i < len; i++) {
    109     ret[i] = '0' + (rand() & 7);
    110   }
    111   ret[i] = 0;
    112 
    113   return ret;
    114 }
    115 
    116 int main(int argc, char **argv) {
    117   _LHASH *lh;
    118   struct dummy_lhash dummy_lh = {NULL};
    119   unsigned i;
    120 
    121   CRYPTO_library_init();
    122 
    123   lh = lh_new(NULL, NULL);
    124 
    125   for (i = 0; i < 100000; i++) {
    126     unsigned action;
    127     char *s, *s1, *s2;
    128 
    129     if (dummy_lh_num_items(&dummy_lh) != lh_num_items(lh)) {
    130       fprintf(stderr, "Length mismatch\n");
    131       return 1;
    132     }
    133 
    134     action = rand() % 3;
    135     switch (action) {
    136       case 0:
    137         s = rand_string();
    138         s1 = (char *)lh_retrieve(lh, s);
    139         s2 = dummy_lh_retrieve(&dummy_lh, s);
    140         if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
    141           fprintf(stderr, "lh_retrieve failure\n");
    142           abort();
    143         }
    144         free(s);
    145         break;
    146 
    147       case 1:
    148         s = rand_string();
    149         lh_insert(lh, (void **)&s1, s);
    150         dummy_lh_insert(&dummy_lh, &s2, strdup(s));
    151 
    152         if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
    153           fprintf(stderr, "lh_insert failure\n");
    154           abort();
    155         }
    156 
    157         if (s1) {
    158           free(s1);
    159         }
    160         if (s2) {
    161           free(s2);
    162         }
    163         break;
    164 
    165       case 2:
    166         s = rand_string();
    167         s1 = lh_delete(lh, s);
    168         s2 = dummy_lh_delete(&dummy_lh, s);
    169 
    170         if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
    171           fprintf(stderr, "lh_insert failure\n");
    172           abort();
    173         }
    174 
    175         if (s1) {
    176           free(s1);
    177         }
    178         if (s2) {
    179           free(s2);
    180         }
    181         free(s);
    182         break;
    183 
    184       default:
    185         abort();
    186     }
    187   }
    188 
    189   lh_doall(lh, free);
    190   lh_free(lh);
    191   dummy_lh_free(&dummy_lh);
    192   printf("PASS\n");
    193   return 0;
    194 }
    195