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