| /*************************************************************************** | 
 |  * Copyright 1995 Michael Veksler. mveksler@vnet.ibm.com | 
 |  *************************************************************************** | 
 |  * File:      hash_test.c | 
 |  * Purpose :  test generic_hash correctness. | 
 |  * NOTE: | 
 |  *   This code covers only about 80% of generic_hash code. | 
 |  *   There might be bugs in the remaining 20% - although most | 
 |  *   of the functionality is tested with wine linckage. | 
 |  *   For complete testing a little more work should be done. | 
 |  *************************************************************************** | 
 |  */ | 
 |  | 
 | #include <stdlib.h> | 
 | #include <stdio.h> | 
 | #include <assert.h> | 
 | #include "generic_hash.h" | 
 |  | 
 | #define SIZE 200 | 
 | typedef struct { int a,b;} DATA ; | 
 | DATA data[SIZE]; | 
 | int keys[SIZE]; | 
 | int peeks=0; | 
 |  | 
 | HASH_CONTAINER *hash1; | 
 | HASH_CONTAINER *hash2;		/* actual data is shared with hash1 */ | 
 |  | 
 | /* test insertion using keys[] and data[] inserting using hash1 and */ | 
 | /* hash2 periodically, test hash after every 2 insertions */ | 
 | void test_insert() | 
 | { | 
 |     int i,j; | 
 |     HASH_VAL *item; | 
 |      | 
 |     printf("testing insertion \n"); | 
 |     for (i=0 ; i < SIZE-1 ; i+=2) { | 
 | 	assert(hash_add_item(hash1, keys[i], (HASH_VAL *)&data[i])); | 
 | 	assert(hash_add_item(hash2, keys[i+1], (HASH_VAL *)&data[i+1])); | 
 | 	for (j=0 ; j <= i+1 ; j++) { | 
 | 	    item= hash_locate_item(hash1, keys[j], (HASH_VAL *)&data[j]); | 
 | 	    if (item == NULL) { | 
 | 		printf("NULL item: i=%d,j=%d\n",i,j); | 
 | 		continue; | 
 | 	    } | 
 | 	    peeks++; | 
 | 	    if (memcmp(item,&data[j],sizeof(DATA))!=0) { | 
 | 		printf("i=%d,j=%d\n",i,j); | 
 | 		printf("saved=(%d,%d), orig=(%d,%d)\n", | 
 | 		       ((DATA*)item)->a, ((DATA*)item)->b, | 
 | 		       data[j].a, data[j].b); | 
 | 	    } | 
 | 	} | 
 |     }  | 
 | } | 
 |  | 
 | /* test deletion using keys[] and data[] deleting using hash1 and */ | 
 | /* hash2 periodicly, test hash after every 2 deletions */ | 
 | void test_delete() | 
 | { | 
 |     int i,j; | 
 |     HASH_VAL *item; | 
 |  | 
 |     printf("testing deletion\n"); | 
 |     for (i=0 ; i < SIZE-1 ; i+=2) { | 
 | 	assert(hash_delete_item(hash2, keys[i], NULL)); | 
 | 	assert(hash_delete_item(hash1, keys[i+1], NULL)); | 
 | 	for (j=0 ; j < SIZE ; j++) { | 
 | 	    item= hash_locate_item(hash2, keys[j], (HASH_VAL *)&data[j]); | 
 | 	    if (item == NULL) { | 
 | 		if ( j > i+1)  | 
 | 		    printf("NULL item: i=%d,j=%d\n",i,j); | 
 | 		continue; | 
 | 	    } | 
 | 	    if (item != NULL && j <= i+1) { | 
 | 		printf("Non NULL item: i=%d,j=%d\n",i,j); | 
 | 		continue; | 
 | 	    } | 
 | 	    if (memcmp(item,&data[j],sizeof(DATA))!=0) { | 
 | 		printf("i=%d,j=%d\n",i,j); | 
 | 		printf("saved=(%d,%d), orig=(%d,%d)\n", | 
 | 		       ((DATA*)item)->a, ((DATA*)item)->b, | 
 | 		       data[j].a, data[j].b); | 
 | 	    } | 
 | 	} | 
 |     }  | 
 |  | 
 | } | 
 |  | 
 |  | 
 | int main() | 
 | { | 
 |     int i; | 
 |      | 
 |     hash1= create_hash(sizeof(DATA), 1); | 
 |     assert(hash1); | 
 |     hash2= attach_remote_hash(hash1->shared, sizeof(DATA), HASH_MEM_ACCESS); | 
 |     assert(hash2); | 
 |  | 
 |     for (i=0 ; i< SIZE ; i++) { | 
 | 	data[i].a= rand(); | 
 | 	data[i].b= rand(); | 
 | 	keys[i]= rand(); | 
 |     } | 
 |  | 
 |     test_insert(); | 
 |     detach_hash(hash1); | 
 |     free(hash1); | 
 |     hash1= attach_remote_hash(hash2->shared, sizeof(DATA), HASH_MEM_ACCESS); | 
 |      | 
 |     test_delete(); | 
 |     test_insert(); | 
 |  | 
 |     detach_hash(hash1); | 
 |     destroy_hash(hash2); | 
 |     printf("peeks=%d\n", peeks); | 
 |     return 0; | 
 | } |