/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_create. */ static int abuse_skiplist_create( void ) { unsigned int i; skiplist_t *skiplist; const unsigned int bad_sizes[] = {0, SKIPLIST_MAX_LINKS + 1, UINT_MAX}; /* Bad property */ skiplist = skiplist_create( 0xffff, 5, int_compare, int_fprintf, NULL ); if( skiplist ) return -1; /* Bad size estimates */ for( i = 0; i < NELEMS( bad_sizes ); ++i ) { skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, bad_sizes[i], int_compare, int_fprintf, NULL ); if( skiplist ) return -1; } /* Bad compare */ skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, SKIPLIST_MAX_LINKS, NULL, int_fprintf, NULL ); if( skiplist ) return -1; /* Bad print */ skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, SKIPLIST_MAX_LINKS, int_compare, NULL, NULL ); if( skiplist ) return -1; return 0; }
/** * @brief TEST_CASE - Confirms that duplicate entries are disallowed when the skiplist is a set. */ static int duplicate_entries_disallowed( void ) { unsigned int i; skiplist_node_t *iter; skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_UNIQUE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; for( i = 0; i < 2; ++i ) { unsigned int j; for( j = 0; j < 5; ++j ) { if( skiplist_insert( skiplist, j ) ) return -1; if( skiplist_size( skiplist, NULL ) != (i ? 5 : j+1) ) return -1; } } for( i = 0; i < 5; ++i ) if( !skiplist_contains( skiplist, i, NULL ) ) return -1; for( i = 0, iter = skiplist_begin( skiplist ); iter != skiplist_end(); iter = skiplist_next( iter ), ++i ) if( skiplist_node_value( iter, NULL ) != i ) return -1; if( skiplist_fprintf_filename( "duplicate_entries_disallowed.dot", skiplist ) ) return -1; return 0; }
/** * @brief TEST_CASE - Sanity test of some key skiplist APIs using integers. */ static int simple( void ) { unsigned int i; skiplist_node_t *iter; skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; if( skiplist_contains( skiplist, 10, NULL ) ) return -1; if( !skiplist_remove( skiplist, 10 ) ) return -1; for( i = 0; i < 10; ++i ) { if( skiplist_insert( skiplist, i ) ) return -1; if( !skiplist_contains( skiplist, i, NULL ) ) return -1; } for( i = 0; i < 100; ++i ) { unsigned int value = rand(); if( skiplist_insert( skiplist, value ) ) return -1; if( !skiplist_contains( skiplist, value, NULL ) ) return -1; } for( i = 5; i < 10; ++i ) if( skiplist_remove( skiplist, i ) ) return -1; for( iter = skiplist_begin( skiplist ); iter != skiplist_end(); iter = skiplist_next( iter ) ) { uintptr_t value = skiplist_node_value( iter, NULL ); if( value >= 5 && value < 10 ) return -1; } for( i = 0; i < skiplist_size( skiplist, NULL ); ++i ) skiplist_at_index( skiplist, i, NULL ); if( skiplist_fprintf_filename( "simple.dot", skiplist ) ) return -1; skiplist_destroy( skiplist ); return 0; }
int main() { struct skiplist *s; struct node *p; int i,level; s = skiplist_create(); for(i=0; i<20; i++) { skiplist_insert(s,rand()%40); } print(s); return 0; }
/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_fprintf. */ static int abuse_skiplist_fprintf( void ) { skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; skiplist_fprintf( NULL, skiplist ); skiplist_fprintf( stdout, NULL ); skiplist_destroy( skiplist ); return 0; }
int main(int argc, char **argv) { ut_init(basename(argv[0])); ut_testing("skiplist_create(6, 50, libhl_cmp_keys_int32, free)"); skiplist_t *skl = skiplist_create(6, 50, libhl_cmp_keys_int32, free); if (skl) ut_success(); else ut_failure("Can't create a new binomial heap"); ut_testing("skiplist_insert(0..99)"); int i; for (i = 0; i < 100; i++) { char *val = malloc(4); snprintf(val, 4, "%d", i); skiplist_insert(skl, &i, sizeof(i), val); } ut_validate_int(skiplist_count(skl), 100); int test_key = 50; ut_testing("skiplist_search(50) = \"50\""); char *val = skiplist_search(skl, &test_key, sizeof(int)); ut_validate_string(val, "50"); ut_testing("skiplist_remove(50, &old_value)"); val = NULL; int rc = skiplist_remove(skl, &test_key, sizeof(int), (void **)&val); ut_validate_int(rc, 0); ut_testing("old_value is \"50\""); ut_validate_string(val, "50"); free(val); ut_testing("skiplist_search(50) = NULL"); val = skiplist_search(skl, &test_key, sizeof(int)); ut_validate_string(val, NULL); skiplist_destroy(skl); ut_summary(); return ut_failed; }
/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_next. */ static int abuse_skiplist_next( void ) { skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; if( skiplist_insert( skiplist, 1 ) ) return -1; if( skiplist_next( NULL ) ) return -1; skiplist_destroy( skiplist ); return 0; }
/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_fprintf_filename. */ static int abuse_skiplist_fprintf_filename( void ) { skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; if( !skiplist_fprintf_filename( NULL, skiplist ) ) return -1; if( !skiplist_fprintf_filename( "valid_filname.txt", NULL ) ) return -1; skiplist_destroy( skiplist ); return 0; }
/** * @brief TEST_CASE - Measures insertion trade off between number of elements in the list and number of links per node. */ static int link_trade_off_insert( void ) { #define MAX_LINKS (SKIPLIST_MAX_LINKS) #define INSERTIONS_LOG2 (16) struct timespec stamps[INSERTIONS_LOG2 + 2]; FILE *fp; unsigned int links; unsigned int i; const char *seperator; fp = fopen( "link_trade_off_insert.gplot", "w" ); if( !fp ) return -1; fprintf(fp, "set term qt\n"); fprintf(fp, "set key off\n"); fprintf(fp, "set logscale\n"); fprintf(fp, "set grid xtics ytics mxtics mytics\n"); fprintf(fp, "set style textbox opaque noborder\n"); fprintf(fp, "set title \"Average Insertion Time for Skiplists with Varying Link Counts\"\n"); fprintf(fp, "set xlabel \"Number of Elements in the Skiplist\"\n"); fprintf(fp, "set ylabel \"Average Time for One Insertion (ns)\"\n"); fprintf(fp, "plot " ); seperator = ""; for( i = 0; i < MAX_LINKS; ++i ) { fprintf(fp, "%s\"link_trade_off_insert_%u.dat\" using 1:2 with lines lt -1," "\"\" using 1:2:($0*0+%u) with labels center boxed notitle", seperator, i + 1, i + 1); seperator = ",\\\n\t"; } fprintf(fp, "\n"); fprintf(fp, "pause -1\n"); fclose( fp ); for( links = MAX_LINKS; links > 0; --links ) { skiplist_t *skiplist; char filename[64]; unsigned int next; sprintf( filename, "link_trade_off_insert_%u.dat", links ); fp = fopen( filename, "w" ); if( !fp ) return -1; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, links, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; next = 0; for( i = 0; i < (1 << INSERTIONS_LOG2); ++i ) { /* Sample at powers of 2. */ if( (i & (i - 1)) == 0 ) { time_stamp( &stamps[next] ); /* Stop trying if it's taking too long. */ if( next && time_diff_ns( &stamps[next - 1], &stamps[next] ) > 300000000LLU ) break; ++next; } if( skiplist_insert( skiplist, rand() ) ) return -1; } time_stamp( &stamps[next] ); ++next; skiplist_destroy( skiplist ); for( i = 1; i < next; ++i ) { const unsigned int node_count = 1 << (i - 1); fprintf(fp, "%u\t%f\n", node_count, time_diff_ns( &stamps[0], &stamps[i] ) / (double)node_count ); } fclose( fp ); } #undef MAX_LINKS #undef INSERTIONS_LOG2 return 0; }
/** * @brief TEST_CASE - Measures lookup trade off between number of elements in the list and number of links per node. */ static int link_trade_off_lookup( void ) { #define MAX_LINKS (SKIPLIST_MAX_LINKS) #define INSERTIONS_LOG2 (16) unsigned int i; FILE *fp; const char *seperator; fp = fopen( "link_trade_off_lookup.gplot", "w" ); if( !fp ) return -1; fprintf(fp, "set term qt\n"); fprintf(fp, "set key off\n"); fprintf(fp, "set logscale\n"); fprintf(fp, "set grid xtics ytics mxtics mytics\n"); fprintf(fp, "set style textbox opaque noborder\n"); fprintf(fp, "set title \"Average Lookup Time for Skiplists with Varying Link Counts\"\n"); fprintf(fp, "set xlabel \"Number of Elements in the Skiplist\"\n"); fprintf(fp, "set ylabel \"Average Time for One Lookup (ns)\"\n"); fprintf(fp, "plot " ); seperator = ""; for( i = 0; i < MAX_LINKS; ++i ) { fprintf(fp, "%s\"link_trade_off_lookup.dat\" using 1:%u with lines lt -1," "\"\" using 1:%u:($0*0+%u) with labels center boxed notitle", seperator, i + 2, i + 2, i + 1); seperator = ",\\\n\t"; } fprintf(fp, "\n"); fprintf(fp, "pause -1\n"); fclose( fp ); fp = fopen( "link_trade_off_lookup.dat", "w" ); if( !fp ) return -1; for( i = 1; i < (1 << INSERTIONS_LOG2); i <<= 1 ) { unsigned int links; fprintf( fp, "%u", i ); for( links = 1; links <= MAX_LINKS; ++links ) { unsigned int j; skiplist_t *skiplist; struct timespec start, end; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, links, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; for( j = 0; j < i; ++j ) if( skiplist_insert( skiplist, j ) ) return -1; time_stamp( &start ); for( j = 0; j < i; ++j ) if( !skiplist_contains( skiplist, j, NULL ) ) return -1; time_stamp( &end ); fprintf( fp, "\t%f", time_diff_ns( &start, &end ) / (double)i ); skiplist_destroy( skiplist ); } fprintf( fp, "\n" ); } fclose( fp ); #undef MAX_LINKS #undef INSERTIONS_LOG2 return 0; }
/** * @brief TEST_CASE - Sanity test of some key skiplist APIs using a pointer to data items. */ static int pointers( void ) { skiplist_t *skiplist; const coord_t coords[] = { /* Simple in order insertion. */ {5,5}, {7,5}, /* Duplicate x with increasing y. */ {5,6}, {5,8}, /* Duplicate x with decreasing y. */ {7,4}, {7,0}, /* Decreasing x. */ {4,5}, {3,5}, /* Increasing x. */ {9,0}, {10,0}, /* Duplicate values. */ {9,0}, {5,5}, /* Zero. */ {0,0}, /* Huge. */ {UINT_MAX,UINT_MAX} }; unsigned int i; skiplist_node_t *iter; coord_t tmp; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 8, coord_compare, coord_fprintf, NULL ); if( !skiplist ) return -1; for( i = 0; i < sizeof(coords) / sizeof(coords[0]); ++i ) if( skiplist_insert( skiplist, (uintptr_t) &coords[i] ) ) return -1; /* Output skiplist for debugging purposes. */ if( skiplist_fprintf_filename( "pointers.dot", skiplist ) ) return -1; /* Confirm skiplist is in the correct order. */ tmp.x = 0; tmp.y = 0; for( iter = skiplist_begin( skiplist ); iter != skiplist_end(); iter = skiplist_next( iter ) ) { coord_t *cur = (coord_t *)skiplist_node_value( iter, NULL ); if( cur->x < tmp.x ) return -1; if( cur->x == tmp.x && cur->y < tmp.y ) return -1; tmp = *cur; } /* Confirm the skiplist contains what we expect. */ for( i = 0; i < sizeof(coords) / sizeof(coords[0]); ++i ) if( !skiplist_contains( skiplist, (uintptr_t) &coords[i], NULL ) ) return -1; /* If we use a different pointer to point to the same values the skiplist should skill contain it. */ tmp = coords[0]; if( !skiplist_contains( skiplist, (uintptr_t) &tmp, NULL ) ) return -1; /* Free resources. */ skiplist_destroy( skiplist ); return 0; }
static int __init skiplist_init(void) { int i; struct timeval start, end; struct skiplist *list; struct skipnode *node; int res = 0; int *key = kmalloc(N * sizeof(int), GFP_KERNEL); if (key == NULL) { printk("-ENOMEM\n"); return -1; } printk("Starting initialization...\n"); list = skiplist_create(); if (list == NULL) { printk("-ENOMEM\n"); return -1; } printk("Started initialization...\n"); printk("Test start!\n"); /* Test 01 */ printk("Test 01: adding and search %d nodes testing!\n", N); printk("Add %d nodes...\n", N); do_gettimeofday(&start); for (i = 0; i < N; i++) { int value = key[i] = i; skiplist_insert(list, key[i], value); } do_gettimeofday(&end); printk("time span:% ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000); #ifdef SKIPLIST_DEBUG skiplist_dump(list); #endif /* Search test */ printk("Now search %d node...\n", N); do_gettimeofday(&start); for (i = 0; i < N; i++) { struct skipnode *node = skiplist_search(list, key[i]); if (node != NULL) { #ifdef SKIPLIST_DEBUG printk("key:%d value:%d\n", node->key, node->value); #endif } else { printk("Not found:%d\n", key[i]); res = 1; break; } } do_gettimeofday(&end); printk("time span:% ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000); if (res) { printk("Test 01: failed!\n"); goto out_clean; } else { printk("Test 01: success!\n"); } /* Test 02 */ printk("Test 02: search single node (%d/2) testing!\n", N); node = skiplist_search(list, N/2); if (node && node->value == N/2) { printk("Test 02: Success!\n"); } else { printk("Test 02: Failed!\n"); res = 1; goto out_clean; } /* Test 03 */ printk("Test 03: remove single node (%d/2) testing!\n", N); skiplist_remove(list, N/2); node = skiplist_search(list, N/2); if (!node) { printk("Test 03: Success!\n"); } else { printk("Test 03: Failed (key:%d)!\n", node->key); res = 1; goto out_clean; } /* Test 04 */ printk("Test 04: search single node equal or great than (%d/2) testing!\n", N); printk("Test 04: case 1: no equal node (%d/2) \n", N); node = skiplist_search_first_eq_big(list, N/2); if (!node || node->value != (N/2 + 1)) { printk("Test 04: Failed!\n"); res = 1; goto out_clean; } printk("Test 04: case 2: has equal node (%d/2 + 1) \n", N); node = skiplist_search_first_eq_big(list, N/2 + 1); if (node && node->value == (N/2 + 1)) { printk("Test 04: Success!\n"); } else { printk("Test 04: Failed!\n"); res = 1; goto out_clean; } /* Test 05 */ res = 0; printk("Test 05: remove all nodes\n"); for (i = 0; i < N; i++) { skiplist_remove(list, key[i]); } for (i = 0; i < N; i++) { node = skiplist_search(list, key[i]); if (node) { res = 1; break; } } if (res) printk("Test 05: Failed!\n"); else printk("Test 05: Success!\n"); #ifdef SKIPLIST_DEBUG skiplist_dump(list); #endif printk("End of Test.\n"); out_clean: skiplist_destroy(list); return 0; }