/* * tabletest - test different implementation of a table. * * Should be compiled together with a table implementation that * follows the interface in table.h of the code base for the * Datastructures and Algorithms courses at the Department of * Computing Science, Umea University. * * 20xx-xx-xx v1.0 Lena Kallin Westin . * 2017-03-xx v1.1 Adam Dahlstrom * Modified to use dynamic memory. * 2017-05-xx v1.2 Niclas Borlin . * Simplified printout and use. Test size can now be * specified on the command line. Lookup (no key) moved * before lookup to avoid cache-hit effects on timing of * mtftable. * 2017-05-xx v1.3 Niclas Borlin . * Added more fine-grained tests. * 2018-02-08 v1.4 Niclas Borlin . * Modified to match 2018 implementation of the data * structure code base. * 2018-02-20 v1.5 Niclas Borlin . * Now completely destroys and rebuilds table between timed * tests to reduce cache effects. * 2018-04-12 v1.6 Niclas Borlin . * Modified program to accept two parameters; number of * elements and number of lookups. * 2018-05-02 v1.7 Niclas Borlin . * Bugfix in get_skewed_lookup_speed. * 2019-02-12 v1.8 Reverted back to single-parameter version v1.6. * 2019-04-17 v1.9 Added -m for machine-readable results. * 2023-02-17 v1.10 Added printout of the codebase version. */ #define VERSION "v1.10" #define VERSION_DATE "2023-02-17" /* * Correctness testing algorithm: * * 1. Tests if isempty returns true directly after a table is created * 2. Tests if isempty returns false directly after a table is created * and one element (key-value-pair) is inserted to it. * 3. Tests a table by creating it and inserting one key-value-pair. After * that it is checked that the returned values from a lookup are the ones * expected. First by looking up a non-existent key, then by looking up * an existent key. * 4. Tests a table by creating it and inserting three key-value-pairs with * unique keys. After that, a lookup for all three keys are tested and * it is checked that the returned values are the ones expected. * 5. Tests a table by creating it and inserting three key-value-pairs with * the same keys. After that, a lookup for the key is tested and it is * checked that the returned value is the last one inserted to the table. * 6. Tests a table by creating it and inserting one key-value-pair. After * that the element is removed and it is checked that the table is empty. * 7. Tests a table by creating it and inserting three key-value-pairs. After * that the elements is removed one at a time and it is checked that the * table is empty after the third element is removed. * 8. Tests a table by creating it and inserting a single key-value * pair followed by three key-value-pairs with identical * keys. After that, the first element is remove and it is verified * that it is gone and that the other key returns the cocorrect * value. The second key is removed and it is checked that the * table is empty. * * There is also a module measuring time for insertions, lookups etc. * */ #include #include #include #include #include #include "table.h" // Maximum size of the table to generate #define TABLESIZE 40000 #define SAMPLESIZE TABLESIZE*2 /** * copy_string() - Create a dynamic copy of a string. * @s: String to be copied. * * Allocates memory for a dynamic copy of s and copies the contents of * s into the copy. * * Returns: Pointer to the copy of s. */ char *copy_string(const char *s) { int len=strlen(s); /* Allocate memory for new string, with an extra char for \0 */ char *dest = malloc(sizeof(char)*(len+1)); /* Malloc failed, return NULL */ if (dest == NULL) { return NULL; } /* Copy content to new memory */ strncpy(dest, s, len); /* Strings should always be null terminated */ dest[len] = '\0'; return dest; } /** * int_ptr_from_int() - Create a dynamic copy of an integer. * @i: String to be copied. * * Allocates memory for a dynamic copy of i and copies the contents of * i into the copy. * * Returns: Pointer to the copy of i. */ int *int_ptr_from_int(int i) { // Allocate memory for a dynamic copy of an integer int *ip=malloc(sizeof(int)); // Copy the value *ip=i; return ip; } /** * get_milliseconds() - Return the current time-of-day in milliseconds. * * Returns: The current time-of-day in milliseconds. */ unsigned long get_milliseconds() { struct timeval tv; gettimeofday(&tv, 0); return (unsigned long)(tv.tv_sec*1000 + tv.tv_usec/1000); } /** * int_compare() - Compare to integers via pointers. * @ip1, @ip2: Pointers to integers to be compared. * * Compares the integers that ip1 and ip2 points to. * * Returns: 0 if the integers are equal, negative if the first * argument is smaller, positive if the first argument is larger. */ int int_compare(const void *ip1,const void *ip2) { const int *n1=ip1; const int *n2=ip2; return (*n1 - *n2); } /** * string_compare() - Compare two strings. * @ip1, @ip2: Pointers to strings to be compared. * * Compares the strings that ip1 and ip2 points to. * * Returns: 0 if the strings are equal, negative if the first * argument is smaller, positive if the first argument is larger. */ int string_compare(const void *ip1,const void *ip2) { const char *s1=ip1; const char *s2=ip2; return strcmp(s1,s2); } /* Shuffles the numbers stored in seq * seq - an array of randomnumbers to be shuffled * n - the number of elements in seq to shuffle, i.e the indexes [0, n] * will be shuffled. However, seq might be larger than n... */ void random_shuffle(int seq[], int n) { for(int i=0;i0 && s[0]=='-') { switch (s[1]) { case 'n': do_test=false; break; case 't': machine_table=true; break; default: fprintf(stderr,"%s: Bad switch: %s.\n", argv[0],s); exit(EXIT_FAILURE); } } else { // Convert string to integer. n=atoi(s); break; } } if (n<0) { fprintf(stderr,"Usage:\n\t%s [-n] [-t] n\n" "\twhere n is an integer from 1 to %d.\n\n" "\tUse -n (no-test) to skip the testing.\n" "\tUse -t (table) to output a machine-readable table with the timings.\n", argv[0],TABLESIZE); exit(EXIT_FAILURE); } if (n<1 || n>TABLESIZE) { fprintf(stderr,"Error: supplied value of n (%d) is outside " "allowed range 1-%d.\n",n,TABLESIZE); exit(EXIT_FAILURE); } if (do_test) { printf("Testing...\n"); correctness_test(); printf("All correctness tests succeeded!\n\n"); } /*getchar();*/ speed_test(n,machine_table); if (!machine_table) { printf("Test completed.\n"); } return 0; }