char *test_findHashElementByKey() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); //simple hash function struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(symbolTable, "blue", symbol); mu_assert("Could not find element that should be table.", findHashElementByKey(symbolTable, "blue") != NULL); mu_assert("Found element that should not be table.", findHashElementByKey(symbolTable, "green") == NULL); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); //normal hash function symbolTable = createHash(&getHashedKeyNormal); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(symbolTable, "teekkekkke", symbol); mu_assert("Could not find element that should be table.", findHashElementByKey(symbolTable, "teekkekkke") != NULL); mu_assert("Found element that should not be table.", findHashElementByKey(symbolTable, "green") == NULL); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
char *test_createHashElement() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); symbol->lvl = 14; //simple hash function struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); mu_assert("Could not created element in empty table.", createHashElement(symbolTable, "blue", symbol) == 0); mu_assert("Could not create element where bucket collison happened.", createHashElement(symbolTable, "boo", symbol) == 0); mu_assert("Level of symbol not same as current lex level.", createHashElement(symbolTable, "blue", symbol) == 1); setLexLevel(symbolTable, 14); mu_assert("Head of symbol linked list hash same lex level as appending symbol.", createHashElement(symbolTable, "blue", symbol) == 3); struct Symbol *symbol2 = calloc(1, sizeof(struct Symbol)); symbol2->lvl = 1; setLexLevel(symbolTable, 1); mu_assert("Appending symbol is at a lower lex level then list head.", createHashElement(symbolTable, "blue", symbol2) == 4); symbol2->lvl = 15; setLexLevel(symbolTable, 15); mu_assert("Could not append symbol where expected.", createHashElement(symbolTable, "blue", symbol2) == 0); // createHashElement(symbolTable, "green", symbol) ; // createHashElement(symbolTable, "red", symbol) ; // dumpHash(symbolTable); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); //normal hash function symbolTable = createHash(&getHashedKeyNormal); mu_assert("Call to createHash does not seg fault.", 1); mu_assert("Could not created element in empty table.", createHashElement(symbolTable, "blue", symbol) == 0); mu_assert("Could not create element where bucket collison happened.", createHashElement(symbolTable, "boo", symbol) == 0); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
char *test_deleteHashElement_single() { // simple hash function struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); int index = getHashIndex(hash, "G"); struct hashElement *element = findHashElementByKey(hash, "GREEN"); mu_assert("unexpected element at in single bucket list.", hash->elements[index] == element); mu_assert("Delete function did not remove single bucket element.", deleteHashElement(hash, "GREEN") == 0); mu_assert("Single element not deleted.", hash->elements[index] == NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); //normal hash function hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); index = getHashIndex(hash, "G"); element = findHashElementByKey(hash, "GREEN"); mu_assert("unexpected element at in single bucket list.", hash->elements[index] == element); mu_assert("Delete function did not remove single bucket element.", deleteHashElement(hash, "GREEN") == 0); mu_assert("Single element not deleted.", hash->elements[index] == NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
char *test_getSizeOfBucket() { //simple hash struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); mu_assert("Expected empty bucket.", getSizeOfBucket(hash, "blue") == 0); createHashElement(hash, "blue", symbol); mu_assert("Expected bucket size of 1.", getSizeOfBucket(hash, "blue") == 1); createHashElement(hash, "red", symbol); createHashElement(hash, "ruby", symbol); createHashElement(hash, "rouse", symbol); createHashElement(hash, "rose", symbol); mu_assert("Expected bucket size of 4.", getSizeOfBucket(hash, "r") == 4); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); //normal hash hash = createHash(&getHashedKeyNormal); mu_assert("Call to createHash does not seg fault.", 1); mu_assert("Expected empty bucket.", getSizeOfBucket(hash, "blue") == 0); createHashElement(hash, "blue", symbol); mu_assert("Expected bucket size of 1.", getSizeOfBucket(hash, "blue") == 1); createHashElement(hash, "red", symbol); createHashElement(hash, "rose", symbol); mu_assert("Expected bucket size of 0.", getSizeOfBucket(hash, "r") == 0); mu_assert("Expected bucket size of 4.", getSizeOfBucket(hash, "red") == 1); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
char *test_createHash() { //simple hash function struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); int index = (*(symbolTable->hashFunction))("b"); mu_assert("Hash function does not caluculate expected value for key 'b'.", index == 98); index = (*(symbolTable->hashFunction))("a"); mu_assert("Hash function does not caluculate expected value for key 'a'.", index == 97); for (int i = 0; i < TABLE_SIZE; ++i) { mu_assert("Empty table bucket does not equal NULL.", symbolTable->elements[i] == NULL); } mu_assert("Expected initial lex level of 0", symbolTable->lexLevel == 0); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); //normal hash function symbolTable = createHash(&getHashedKeyNormal); mu_assert("Call to createHash does not seg fault.", 1); index = (*(symbolTable->hashFunction))("A"); mu_assert("Hash function does not caluculate expected value for key 'A'.", index == 638); index = (*(symbolTable->hashFunction))("aaa"); mu_assert("Hash function does not caluculate expected value for key 'a'.", index == 928); for (int i = 0; i < TABLE_SIZE; ++i) { mu_assert("Empty table bucket does not equal NULL.", symbolTable->elements[i] == NULL); } mu_assert("Expected initial lex level of 0", symbolTable->lexLevel == 0); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//can't test on normal hash function. can't find collisons char *test_deleteHashElement_end() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); struct hashElement *element = findHashElementByKey(hash, "bbbb"); struct hashElement *newTail = element->prev; mu_assert("unexpected element at end of list.", element->next == NULL); mu_assert("Delete function did not remove end element.", deleteHashElement(hash, "bbbb") == 0); mu_assert("End element not deleted.", newTail->next == NULL); mu_assert("Did not delete end of list propertly.", newTail->prev != NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//can't test on normal hash function. can't find collisons char *test_deleteHashElement_begining() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); struct hashElement *element = findHashElementByKey(hash, "bb"); struct hashElement *newHead = element->next; int index = getHashIndex(hash, "b"); mu_assert("unexpected element at head of bucket list.", hash->elements[index] == element); mu_assert("Delete function did not remove begining element.", deleteHashElement(hash, "bb") == 0); mu_assert("Begining element not deleted.", hash->elements[index] == newHead); mu_assert("Did not delete front of list propertly.", newHead->prev == NULL); mu_assert("Resulting bucket should have more than one element.", newHead->next != NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//can't test on normal hash function. can't find collisons char *test_isKeyInBucket() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(symbolTable, "blue", symbol); createHashElement(symbolTable, "boo", symbol); createHashElement(symbolTable, "bobby", symbol); mu_assert("Could not find expected key 'blue' in bucket.", isKeyInBucket(symbolTable, "blue") == 1 ); mu_assert("Could not find expected key 'blue' in bucket.", isKeyInBucket(symbolTable, "bobby") == 1 ); mu_assert("Could not find expected key 'blue' in bucket.", isKeyInBucket(symbolTable, "gree") == 0 ); mu_assert("Could not find expected key 'blue' in bucket.", isKeyInBucket(symbolTable, "boo") == 1 ); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//can't test on normal hash function. can't find collisons char *test_deleteHashElement_middle() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); struct hashElement *element = findHashElementByKey(hash, "bbb"); struct hashElement *head = findHashElementByKey(hash, "bb"); struct hashElement *tail = findHashElementByKey(hash, "bbbb"); mu_assert("unexpected element after head.", head->next == element); mu_assert("unexpected element before tail.", tail->prev == element); mu_assert("Delete function did not remove middle element.", deleteHashElement(hash, "bbb") == 0); mu_assert("Did not reset next in list propertly.", head->next == tail); mu_assert("Did not reset prev in list propertly", tail->prev == head); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
char *test_dumpHash() { struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); dumpHash(hash); mu_assert("Hash dump seg faults.", 1); /*test 2: Copy stdout to to buffer and compare out of empty symbol table.*/ char buffer[100] = {0}; int out_pipe[2]; int saved_stdout = dup(STDOUT_FILENO); /* save stdout for display later */ pipe(out_pipe); /* make a pipe */ dup2(out_pipe[1], STDOUT_FILENO); /* redirect stdout to the pipe */ close(out_pipe[1]); dumpHash(hash); /* anything sent to printf should now go down the pipe */ fflush(stdout); read(out_pipe[0], buffer, 100); //read from pipe into buffer dup2(saved_stdout, STDOUT_FILENO); /* reconnect stdout for testing */ char expectedOutput[33] = "\n\nDUMPING HASH:\nDUMP COMPLETE.\n\n"; mu_assert("Hash dumper gives unexpected output on empty hash.", strcmp(expectedOutput, buffer) == 0); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); // createHashElement(hash, "blue", 123); // createHashElement(hash, "boo", 23456); // createHashElement(hash, "bobby", 123); // dumpHash(hash); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
char *test_destroyHash() { struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); for (int i = 0; i < TABLE_SIZE; ++i) { mu_assert("destroyed bucket does not equal NULL.", symbolTable->elements[i] == NULL); } destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
char *test_getHashIndex() { //simple hash function struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); int index = getHashIndex(symbolTable, "b"); mu_assert("getHashIndex does not return expected value on key 'b'", index == 98); index = getHashIndex(symbolTable, "W"); mu_assert("getHashIndex does not return expected value on key 'b'", index == 87); index = getHashIndex(symbolTable, "="); mu_assert("getHashIndex does not return expected value on key 'b'", index == 61); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); //normal hash function symbolTable = createHash(&getHashedKeyNormal); mu_assert("Call to createHash does not seg fault.", 1); index = getHashIndex(symbolTable, "b"); mu_assert("getHashIndex does not return expected value on key 'b'", index == 671); index = getHashIndex(symbolTable, "W"); mu_assert("getHashIndex does not return expected value on key 'b'", index == 660); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//not testing on normal hash to hard to find collisons char *test_isKeyCollison() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); mu_assert("Collision on empty symbol table.", isKeyCollison(symbolTable, "blue") == 0); createHashElement(symbolTable, "blue", symbol); mu_assert("Could not find key collision where one should exist.", isKeyCollison(symbolTable, "blue") == 1); mu_assert("Found key collision where one should not exist.", isKeyCollison(symbolTable, "green") == 0); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//can't test on normal hash function. can't find collisons char *test_getHashBucketHead() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *symbolTable = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(symbolTable, "blue", symbol); createHashElement(symbolTable, "boo", symbol); createHashElement(symbolTable, "bobby", symbol); mu_assert("Returned pointer when NULL was expected in getHashBucketHead.", getHashBucketHead(symbolTable, "gree") == NULL ); mu_assert("Returned bucket head is incorrect.", getHashBucketHead(symbolTable, "b") == findHashElementByKey(symbolTable, "blue") ); mu_assert("Returned bucket head is incorrect.", getHashBucketHead(symbolTable, "bobby") != findHashElementByKey(symbolTable, "bobby") ); destroyHash(&symbolTable); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//This helper function resizes the data structure Hash. //Handles collisions by using chaining as a means of rehashing. //Returns void. static void grow(Hash h){ Hash h2; struct hash_table swap; //Temporary structure for the swaps struct element *elt; int i; h2 = createHashIntern((h -> size) * GROWTH_FACTOR); for (i = 0; i < h -> size; i++){ for (elt = h -> table[i]; elt != 0; elt = elt -> next){ insertElement(h2, elt -> key, elt -> value, elt -> length); //Recopies everything } } //Swap the contents of the hash table h and h2. swap = *h; *h = *h2; *h2 = swap; destroyHash(h2); }
int main(int argc, char* argv[]) { //local variables HashTable *inverted_index, *test_index; char *target_dir, *results_file1, *results_file2, *rewritten_file; target_dir = results_file1 = results_file2 = rewritten_file=NULL; // 1. Program parameter processing //./indexer [TARGET_DIRECTORY] [RESULTS FILENAME1] [RESULTS FILENAME2] [REWRITEN FILENAME] //or // ./indexer [TARGET_DIRECTORY] [RESULTS FILENAME] if(argc == 3 || argc == 5) { target_dir = calloc(strlen(argv[1])+1, sizeof(char)); if(target_dir == NULL) { LOG(stdout,"Error: failed to calloc the variable target_dir\n"); return 1; } if( strcpy(target_dir, argv[1]) == NULL) { LOG(stdout,"Error: failed to strcpy to the variable target_dir\n"); return 1; } //check if the directory is valid if(IsDir(target_dir)) { printf("%s is a directory\n", target_dir); } else { printf("Error: %s is NOT a directory\n", target_dir); free(target_dir); return 1; } results_file1 = calloc(strlen(argv[2])+1, sizeof(char)); if(results_file1 == NULL) { LOG(stdout,"Error: failed to calloc the variable results_file1\n"); return 1; } if( strcpy(results_file1, argv[2]) == NULL) { LOG(stdout,"Error: failed to strcpy to the variable results_file1\n"); return 1; } if(argc == 5) { results_file2 = calloc(strlen(argv[3])+1, sizeof(char)); if(results_file2 == NULL) { LOG(stdout,"Error: failed to calloc the varaible results_file2\n"); free(target_dir); free(results_file1); return 1; } if( strcpy(results_file2, argv[3]) == NULL) { LOG(stdout,"Error: failed to strcpy to variable results_file2\n"); free(target_dir); free(results_file1); return 1; } rewritten_file = calloc(strlen(argv[4])+1, sizeof(char)); if(rewritten_file == NULL) { LOG(stdout,"Error: failed to calloc rewritten_file\n"); free(target_dir); free(results_file1); free(results_file2); return 1; } if( strcpy(rewritten_file, argv[4]) == NULL) { LOG(stdout,"Error: failed to strcpy to variable rewritten_file\n"); free(target_dir); free(results_file1); free(results_file2); return 1; } } } else { //wrong input parameters, inform the user about it. printf("Usage: ./indexer [TARGET_DIRECTORY] [RESULTS FILENAME]\n"); printf(" or ./indexer [TARGET_DIRECTORY] [RESULTS FILENAME1] [RESULTS FILENAME2] [REWRITEN FILENAME]\n"); printf("You have entered %d parameters\n", (argc - 1)); return 1; } // 2. Initialize data structures // allocate Inverted_index, zero it, and set links to NULL. inverted_index = calloc(1, sizeof(HashTable)); if(inverted_index == NULL) { LOG(stdout,"Error: failed to calloc the variable inverted_index\n"); return 1; } // 3.print to stdout that the building of index is starting //printf("\nStarting to build the index\n"); LOG(stdout,"Starting to build the index\n"); // 4. Build the inverted index if(buildIndexFromDirectory (inverted_index, target_dir)) { LOG(stdout, "Error: buildIndexFromDirectory() failed\n"); return 1; } LOG(stdout,"Building the inverted index\n"); // 5. Save the inverted index if(!saveFile(inverted_index, results_file1)) { LOG(stdout,"Successfully saved the inverted index\n"); } else { LOG(stdout, "Error: saveFile() failed\n"); } // 6. Free appropriate memory destroyHash(inverted_index); free(target_dir); free(results_file1); // 7. If 4 input parameters are detected if(5 == argc) { test_index = calloc(1, sizeof(HashTable)); if(test_index == NULL) { LOG(stdout, "Error: failed to calloc the variable test_index\n"); free(results_file2); free(rewritten_file); destroyHash(test_index); return 1; } if(!IsFile(results_file2)) { printf("Error: %s is not a file\n", results_file2); free(results_file2); free(rewritten_file); destroyHash(test_index); return 1; } // 8. Inform user that testing has started LOG(stdout, "Starting the testing process\n"); // 9. Reload the index from the file and rewrite it to a new file if(readFile(test_index, results_file2)) { LOG(stdout,"Error: readFile failed\n"); free(results_file2); free(rewritten_file); destroyHash(test_index); return 1; } // 10. save the reconstructed index if(saveFile(test_index, rewritten_file)) { LOG(stdout,"Error: saveFile(test_index, rewritten_file) failed\n"); free(results_file2); free(rewritten_file); destroyHash(test_index); return 1; } else { LOG(stdout,"Successfully saved the inverted index\n"); } // 11. free appropriate memory free(results_file2); free(rewritten_file); destroyHash(test_index); LOG(stdout,"Test is complete\n"); } // 12. Finished LOG(stdout,"indexer.c has finished\n"); return 0; }
int main (int argc, char *argv[]) { if (argc != 4) return 3; int M = strtol(argv[1], NULL, 10); //get numerical value from string //open input file FILE *in = fopen(argv[2], "r"); if (!in) return 2; //open output file FILE *out = fopen(argv[3], "w"); if (!out) { fclose(in); return 2; } //buffer input which will be used to parse commands //aux is used to check return value of function fgets //aux tells us when to stop reading char *aux = NULL, *buffer = NULL; buffer = malloc(BSIZE * sizeof(char)); if (!buffer) { fclose(in); fclose(out); return 2; } THash *H = initHash(M); if (!H) { fclose(in); fclose(out); free(buffer); return 2; } aux = fgets(buffer, BSIZE, in); while (aux) { if (buffer[0] == '\n') break; //limit case when end of file reached (almost) and last line is '\n' buffer[strlen(buffer) - 1] = '\0'; //try to parse commands //if command is put and memory cannot be allocated then exit program (clean) if (parse(H, buffer, out) == -1) { fclose(in); fclose(out); free(buffer); destroyHash(&H, freeInf); return 2; } aux = fgets(buffer, BSIZE, in); } //free everything destroyHash(&H, freeInf); fclose(in); fclose(out); free(buffer); return 0; }