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#if !defined(_POSIX_C_SOURCE) 16#define _POSIX_C_SOURCE 201410L 17#endif 18 19#include <openssl/crypto.h> 20#include <openssl/lhash.h> 21 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25 26struct dummy_lhash_node { 27 char *s; 28 struct dummy_lhash_node *next; 29}; 30 31struct dummy_lhash { 32 struct dummy_lhash_node *head; 33}; 34 35static void dummy_lh_free(struct dummy_lhash *lh) { 36 struct dummy_lhash_node *cur, *next; 37 38 for (cur = lh->head; cur != NULL; cur = next) { 39 next = cur->next; 40 free(cur->s); 41 free(cur); 42 } 43} 44 45static size_t dummy_lh_num_items(const struct dummy_lhash *lh) { 46 size_t count = 0; 47 struct dummy_lhash_node *cur; 48 49 for (cur = lh->head; cur != NULL; cur = cur->next) { 50 count++; 51 } 52 53 return count; 54} 55 56static char *dummy_lh_retrieve(struct dummy_lhash *lh, const char *s) { 57 struct dummy_lhash_node *cur; 58 59 for (cur = lh->head; cur != NULL; cur = cur->next) { 60 if (strcmp(cur->s, s) == 0) { 61 return cur->s; 62 } 63 } 64 65 return NULL; 66} 67 68static int dummy_lh_insert(struct dummy_lhash *lh, char **old_data, char *s) { 69 struct dummy_lhash_node *node, *cur; 70 71 for (cur = lh->head; cur != NULL; cur = cur->next) { 72 if (strcmp(cur->s, s) == 0) { 73 *old_data = cur->s; 74 cur->s = s; 75 return 1; 76 } 77 } 78 79 node = malloc(sizeof(struct dummy_lhash_node)); 80 *old_data = NULL; 81 node->s = s; 82 node->next = lh->head; 83 lh->head = node; 84 return 1; 85} 86 87static char *dummy_lh_delete(struct dummy_lhash *lh, const void *s) { 88 struct dummy_lhash_node *cur, **next_ptr; 89 char *ret; 90 91 next_ptr = &lh->head; 92 for (cur = lh->head; cur != NULL; cur = cur->next) { 93 if (strcmp(cur->s, s) == 0) { 94 ret = cur->s; 95 *next_ptr = cur->next; 96 free(cur); 97 return ret; 98 } 99 next_ptr = &cur->next; 100 } 101 102 return NULL; 103} 104 105static char *rand_string(void) { 106 unsigned len = 1 + (rand() % 3); 107 char *ret = malloc(len + 1); 108 unsigned i; 109 110 for (i = 0; i < len; i++) { 111 ret[i] = '0' + (rand() & 7); 112 } 113 ret[i] = 0; 114 115 return ret; 116} 117 118int main(int argc, char **argv) { 119 _LHASH *lh; 120 struct dummy_lhash dummy_lh = {NULL}; 121 unsigned i; 122 123 CRYPTO_library_init(); 124 125 lh = lh_new(NULL, NULL); 126 if (lh == NULL) { 127 return 1; 128 } 129 130 for (i = 0; i < 100000; i++) { 131 unsigned action; 132 char *s, *s1, *s2; 133 134 if (dummy_lh_num_items(&dummy_lh) != lh_num_items(lh)) { 135 fprintf(stderr, "Length mismatch\n"); 136 return 1; 137 } 138 139 action = rand() % 3; 140 switch (action) { 141 case 0: 142 s = rand_string(); 143 s1 = (char *)lh_retrieve(lh, s); 144 s2 = dummy_lh_retrieve(&dummy_lh, s); 145 if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) { 146 fprintf(stderr, "lh_retrieve failure\n"); 147 abort(); 148 } 149 free(s); 150 break; 151 152 case 1: 153 s = rand_string(); 154 lh_insert(lh, (void **)&s1, s); 155 dummy_lh_insert(&dummy_lh, &s2, strdup(s)); 156 157 if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) { 158 fprintf(stderr, "lh_insert failure\n"); 159 abort(); 160 } 161 162 if (s1) { 163 free(s1); 164 } 165 if (s2) { 166 free(s2); 167 } 168 break; 169 170 case 2: 171 s = rand_string(); 172 s1 = lh_delete(lh, s); 173 s2 = dummy_lh_delete(&dummy_lh, s); 174 175 if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) { 176 fprintf(stderr, "lh_insert failure\n"); 177 abort(); 178 } 179 180 if (s1) { 181 free(s1); 182 } 183 if (s2) { 184 free(s2); 185 } 186 free(s); 187 break; 188 189 default: 190 abort(); 191 } 192 } 193 194 lh_doall(lh, free); 195 lh_free(lh); 196 dummy_lh_free(&dummy_lh); 197 printf("PASS\n"); 198 return 0; 199} 200