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