2014-06-20 20:00:00 +01:00
|
|
|
/* Copyright (c) 2014, Google Inc.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
|
|
|
|
2014-10-02 21:58:19 +01:00
|
|
|
#define _POSIX_C_SOURCE 201410L
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-09-12 00:11:15 +01:00
|
|
|
#include <openssl/crypto.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <openssl/lhash.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
struct dummy_lhash_node {
|
|
|
|
char *s;
|
|
|
|
struct dummy_lhash_node *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dummy_lhash {
|
|
|
|
struct dummy_lhash_node *head;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void dummy_lh_free(struct dummy_lhash *lh) {
|
|
|
|
struct dummy_lhash_node *cur, *next;
|
|
|
|
|
|
|
|
for (cur = lh->head; cur != NULL; cur = next) {
|
|
|
|
next = cur->next;
|
|
|
|
free(cur->s);
|
|
|
|
free(cur);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t dummy_lh_num_items(const struct dummy_lhash *lh) {
|
|
|
|
size_t count = 0;
|
|
|
|
struct dummy_lhash_node *cur;
|
|
|
|
|
|
|
|
for (cur = lh->head; cur != NULL; cur = cur->next) {
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *dummy_lh_retrieve(struct dummy_lhash *lh, const char *s) {
|
|
|
|
struct dummy_lhash_node *cur;
|
|
|
|
|
|
|
|
for (cur = lh->head; cur != NULL; cur = cur->next) {
|
|
|
|
if (strcmp(cur->s, s) == 0) {
|
|
|
|
return cur->s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dummy_lh_insert(struct dummy_lhash *lh, char **old_data, char *s) {
|
|
|
|
struct dummy_lhash_node *node, *cur;
|
|
|
|
|
|
|
|
for (cur = lh->head; cur != NULL; cur = cur->next) {
|
|
|
|
if (strcmp(cur->s, s) == 0) {
|
|
|
|
*old_data = cur->s;
|
|
|
|
cur->s = s;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
node = malloc(sizeof(struct dummy_lhash_node));
|
|
|
|
*old_data = NULL;
|
|
|
|
node->s = s;
|
|
|
|
node->next = lh->head;
|
|
|
|
lh->head = node;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *dummy_lh_delete(struct dummy_lhash *lh, const void *s) {
|
|
|
|
struct dummy_lhash_node *cur, **next_ptr;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
next_ptr = &lh->head;
|
|
|
|
for (cur = lh->head; cur != NULL; cur = cur->next) {
|
|
|
|
if (strcmp(cur->s, s) == 0) {
|
|
|
|
ret = cur->s;
|
|
|
|
*next_ptr = cur->next;
|
|
|
|
free(cur);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
next_ptr = &cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
static char *rand_string(void) {
|
2014-07-09 00:10:12 +01:00
|
|
|
unsigned len = 1 + (rand() % 3);
|
2014-06-20 20:00:00 +01:00
|
|
|
char *ret = malloc(len + 1);
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2014-07-09 00:10:12 +01:00
|
|
|
ret[i] = '0' + (rand() & 7);
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
ret[i] = 0;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
2014-09-12 00:11:15 +01:00
|
|
|
_LHASH *lh;
|
2014-06-20 20:00:00 +01:00
|
|
|
struct dummy_lhash dummy_lh = {NULL};
|
|
|
|
unsigned i;
|
|
|
|
|
2014-09-12 00:11:15 +01:00
|
|
|
CRYPTO_library_init();
|
|
|
|
|
|
|
|
lh = lh_new(NULL, NULL);
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
for (i = 0; i < 100000; i++) {
|
|
|
|
unsigned action;
|
|
|
|
char *s, *s1, *s2;
|
|
|
|
|
|
|
|
if (dummy_lh_num_items(&dummy_lh) != lh_num_items(lh)) {
|
|
|
|
fprintf(stderr, "Length mismatch\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-07-09 00:10:12 +01:00
|
|
|
action = rand() % 3;
|
2014-06-20 20:00:00 +01:00
|
|
|
switch (action) {
|
|
|
|
case 0:
|
2014-07-09 00:10:12 +01:00
|
|
|
s = rand_string();
|
2014-06-20 20:00:00 +01:00
|
|
|
s1 = (char *)lh_retrieve(lh, s);
|
|
|
|
s2 = dummy_lh_retrieve(&dummy_lh, s);
|
|
|
|
if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
|
|
|
|
fprintf(stderr, "lh_retrieve failure\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
free(s);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2014-07-09 00:10:12 +01:00
|
|
|
s = rand_string();
|
2014-06-20 20:00:00 +01:00
|
|
|
lh_insert(lh, (void **)&s1, s);
|
|
|
|
dummy_lh_insert(&dummy_lh, &s2, strdup(s));
|
|
|
|
|
|
|
|
if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
|
|
|
|
fprintf(stderr, "lh_insert failure\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s1) {
|
|
|
|
free(s1);
|
|
|
|
}
|
|
|
|
if (s2) {
|
|
|
|
free(s2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2014-07-09 00:10:12 +01:00
|
|
|
s = rand_string();
|
2014-06-20 20:00:00 +01:00
|
|
|
s1 = lh_delete(lh, s);
|
|
|
|
s2 = dummy_lh_delete(&dummy_lh, s);
|
|
|
|
|
|
|
|
if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
|
|
|
|
fprintf(stderr, "lh_insert failure\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s1) {
|
|
|
|
free(s1);
|
|
|
|
}
|
|
|
|
if (s2) {
|
|
|
|
free(s2);
|
|
|
|
}
|
|
|
|
free(s);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lh_doall(lh, free);
|
|
|
|
lh_free(lh);
|
|
|
|
dummy_lh_free(&dummy_lh);
|
|
|
|
printf("PASS\n");
|
|
|
|
return 0;
|
|
|
|
}
|