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 
26 struct dummy_lhash_node {
27   char *s;
28   struct dummy_lhash_node *next;
29 };
30 
31 struct dummy_lhash {
32   struct dummy_lhash_node *head;
33 };
34 
dummy_lh_free(struct dummy_lhash * lh)35 static 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 
dummy_lh_num_items(const struct dummy_lhash * lh)45 static 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 
dummy_lh_retrieve(struct dummy_lhash * lh,const char * s)56 static 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 
dummy_lh_insert(struct dummy_lhash * lh,char ** old_data,char * s)68 static 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 
dummy_lh_delete(struct dummy_lhash * lh,const void * s)87 static 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 
rand_string(void)105 static 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 
main(int argc,char ** argv)118 int 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