// file: $isip/class/dstr/HashTable/HashTableDiagnose.h // version: $Id: HashTableDiagnose.h 6852 2001-04-30 02:03:57Z duncan $ // // make sure definitions are only made once // #ifndef ISIP_HASH_TABLE_DIAGNOSE #define ISIP_HASH_TABLE_DIAGNOSE // isip include files // #ifndef ISIP_HASH_TABLE #include #endif // HashTableDiagnose: a class that contains the diagnose method of // HashTable class. // template class HashTableDiagnose : public HashTable { //--------------------------------------------------------------------------- // // public constants // //--------------------------------------------------------------------------- public: // define the class name // //---------------------------------------- // // i/o related constants // //---------------------------------------- //---------------------------------------- // // default values and arguments // //---------------------------------------- // default values // // default arguments to methods // //---------------------------------------- // // error codes // //---------------------------------------- //--------------------------------------------------------------------------- // // protected data // //--------------------------------------------------------------------------- protected: //--------------------------------------------------------------------------- // // required public methods // //--------------------------------------------------------------------------- public: // method: name // static const String& name() { return HashTable::name(); } // other static methods // static boolean diagnose(Integral::DEBUG debug_level); // debug methods // these methods are omitted since this class does not have data // members and operations // // destructor/constructor(s): // these methods are omitted since this class does not have data // members and operations // // assign methods: // these methods are omitted since this class does not have data // members and operations // // operator= methods: // these methods are omitted since this class does not have data // members and operations // // i/o methods: // these methods are omitted since this class does not have data // members and operations // // equality methods: // these methods are omitted since this class does not have data // members and operations // // memory-management methods: // these methods are omitted since this class does not have data // members and operations // //--------------------------------------------------------------------------- // // class-specific public methods // //--------------------------------------------------------------------------- // these methods are omitted since this class does not have data // members and operations // //--------------------------------------------------------------------------- // // private methods // //--------------------------------------------------------------------------- private: }; // below are all the methods for the HashTableDiagnose template class // //----------------------------------------------------------------------------- // // required static methods // //----------------------------------------------------------------------------- // method: diagnose // // arguments: // Integral::DEBUG level: (input) debug level for diagnostics // // return: a boolean value indicating status // template boolean HashTableDiagnose::diagnose(Integral::DEBUG level_a) { //---------------------------------------------------------------------- // // 0. preliminaries // //---------------------------------------------------------------------- // output the class name // if (level_a > Integral::NONE) { SysString output(L"diagnosing class "); output.concat(CLASS_NAME); output.concat(L": "); Console::put(output); Console::increaseIndention(); } //--------------------------------------------------------------------- // // 1. required public methods // //--------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing required public methods...\n"); Console::increaseIndention(); } // test the debug methods // setDebug(debug_level_d); if (level_a > Integral::BRIEF) { Integral::debug(L"debug"); } // prepare items and keys for all the hash tables used in this diagnose // long num_elem = 20; Char** items = new Char*[num_elem]; String* keys = new String[num_elem]; Char key_char; for (long i = 0; i < num_elem; i++) { items[i] = new Char((unichar)((int)'a' + i)); key_char.assign((unichar)((int)'a' + i)); keys[i].assign(key_char); keys[i].concat(L"-key"); } // we change some keys in order to create some collisions // keys[5].assign(L"ab-key"); // hashes to 17 from 49 keys[9].assign(L"az-key"); // hashes to 17 from 49 keys[13].assign(L"ad-key"); // hashes to 17 from 49 keys[15].assign(L"ah-key"); // hashes to 1 from 49 keys[19].assign(L"aa-key"); // hashes to 1 from 49 // test constructors // HashTable def_htable(SYSTEM, (long)50); if (def_htable.getCapacity() != (long)50) { Long cap = def_htable.getCapacity(); cap.debug(L"capacity"); return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_htable.insert(keys[i], items[i]); } // copy constructor // HashTable copy_htable(def_htable); // the two constructed hash tables should be the same now // if (def_htable.ne(copy_htable)) { def_htable.debug(L"def_htable"); return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } { // test constructors // HashTable def_htable; if (def_htable.getCapacity() != (long)128) { return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_htable.insert(keys[i], items[i]); } // copy constructor // HashTable copy_htable(def_htable); // the two constructed hash tables should be the same now // if (def_htable.ne(copy_htable)) { def_htable.debug(L"def_htable"); return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } } // check the constructors and destructors for allocating on the dynamic // memory heap // HashTable* def_dyn_htable = new HashTable(SYSTEM, (long)50); if (def_dyn_htable->getCapacity() != (long)50) { return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_dyn_htable->insert(keys[i], items[i]); } HashTable* copy_dyn_htable = new HashTable(*def_dyn_htable); // the two constructed hash tables should be the same now // if (def_dyn_htable->ne(*copy_dyn_htable)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // see if we can dynamically delete // delete def_dyn_htable; delete copy_dyn_htable; { // check the constructors and destructors for allocating on the dynamic // memory heap // HashTable* def_dyn_htable = new HashTable(); if (def_dyn_htable->getCapacity() != (long)128) { return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_dyn_htable->insert(keys[i], items[i]); } HashTable* copy_dyn_htable = new HashTable(*def_dyn_htable); // the two constructed hash tables should be the same now // if (def_dyn_htable->ne(*copy_dyn_htable)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // see if we can dynamically delete // delete def_dyn_htable; delete copy_dyn_htable; } // check the constructors for allocating on the stack // HashTable def_htable_2(USER, (long)50); if (def_htable_2.getCapacity() != (long)50) { return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_htable_2.insert(keys[i], items[i]); } // copy constructor // HashTable copy_htable_2(def_htable_2); // the two constructed hash tables should be the same now // if (def_htable_2.ne(copy_htable_2)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } { // check the constructors for allocating on the stack // HashTable def_htable_2(USER); if (def_htable_2.getCapacity() != (long)128) { return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_htable_2.insert(keys[i], items[i]); } // copy constructor // HashTable copy_htable_2(def_htable_2); // the two constructed hash tables should be the same now // if (def_htable_2.ne(copy_htable_2)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } } // check the constructors and destructors for allocating on the dynamic // memory heap // HashTable* def_dyn_htable_2 = new HashTable(USER, (long)50); if (def_dyn_htable_2->getCapacity() != (long)50) { return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_dyn_htable_2->insert(keys[i], items[i]); } HashTable* copy_dyn_htable_2 = new HashTable(*def_dyn_htable_2); // the two constructed hash tables should be the same now // if (def_dyn_htable_2->ne(*copy_dyn_htable_2)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // see if we can dynamically delete // delete def_dyn_htable_2; delete copy_dyn_htable_2; { // check the constructors and destructors for allocating on the dynamic // memory heap // HashTable* def_dyn_htable_2 = new HashTable(USER); if (def_dyn_htable_2->getCapacity() != (long)128) { return Error::handle(name(), L"constructor", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < num_elem; i++) { def_dyn_htable_2->insert(keys[i], items[i]); } HashTable* copy_dyn_htable_2 = new HashTable(*def_dyn_htable_2); // the two constructed hash tables should be the same now // if (def_dyn_htable_2->ne(*copy_dyn_htable_2)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // see if we can dynamically delete // delete def_dyn_htable_2; delete copy_dyn_htable_2; } // test large allocation construction and deletion // if (level_a >= Integral::ALL) { // output an informative message // Console::put(L"\ntesting large chunk memory allocation and deletion:\n"); // set the memory to a strange block size so we can hopefully catch any // frame overrun errors // HashTable::setGrowSize((long)13); // loop for a large number of times creating and deleting a large number // of htables at each loop // for (long j = 1; j <= 10; j++) { HashTable** htables = new HashTable*[j * 50]; HashTable** system_htables = new HashTable*[j * 50]; // create the items // for (long i = 0; i < j * 50; i++) { system_htables[i] = new HashTable(); htables[i] = new HashTable(USER); } // delete hash tables // for (long i = (j * 50) - 1; i >= 0; i--) { delete htables[i]; delete system_htables[i]; } // clean up memory // delete [] htables; delete [] system_htables; } } // test assign methods // HashTable tmp_htable; HashTable* tmp_dyn_htable = new HashTable(); // USER-allocated // HashTable tmp_htable_1(USER); HashTable* tmp_dyn_htable_1 = new HashTable(USER); // add some items into the htable // for (long i = 0; i < num_elem; i++) { tmp_htable.insert(keys[i], items[i]); } // try the htable assign method // tmp_dyn_htable->assign(tmp_htable); tmp_htable_1.assign(*tmp_dyn_htable_1); if ((tmp_htable_1.ne(*tmp_dyn_htable_1)) || (tmp_dyn_htable_1->ne(tmp_htable_1))) { return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__); } if ((tmp_dyn_htable->ne(tmp_htable)) || (tmp_htable.ne(*tmp_dyn_htable))) { return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__); } // clean up // delete tmp_dyn_htable; delete tmp_dyn_htable_1; // testing i/o methods // String text_filename; Integral::makeTemp(text_filename); String bin_filename; Integral::makeTemp(bin_filename); // open files in write mode // Sof text_file; text_file.open(text_filename, File::WRITE_ONLY, File::TEXT); Sof bin_file; bin_file.open(bin_filename, File::WRITE_ONLY, File::BINARY); // prepare items for the htables // Char** write_chars = new Char*[10]; String** write_strings = new String*[10]; Vector* vec_chars = new Vector[10]; unichar tmp_char = L'a'; for (long i = 0; i < 10; i++) { write_chars[i] = new Char(tmp_char); write_strings[i] = new String(); vec_chars[i].setLength(5); vec_chars[i].assign(*write_chars[i]); tmp_char++; } write_strings[0]->assign(L"this "); write_strings[1]->assign(L"is"); write_strings[2]->assign(L"a"); write_strings[3]->assign(L"HashTable"); write_strings[4]->assign(L"String"); write_strings[5]->assign(L"this "); write_strings[6]->assign(L"is"); write_strings[7]->assign(L"in"); write_strings[8]->assign(L"the"); write_strings[9]->assign(L"diagnose"); // create hash tables to write, we set a small capacity on purpose // HashTable write_char_htable(USER, (long)20); HashTable write_str_htable(USER, (long)20); HashTable > write_vec_char_htable(USER, (long)20); HashTable write_empty_hash; HashTable write_nested_hash; Long l; l = 8; String object_name(L"Object"); write_nested_hash.insert(object_name, &l); for ( long i = 0; i < 10; i++) { write_char_htable.insert(keys[i], write_chars[i]); write_str_htable.insert(keys[i], write_strings[i]); write_vec_char_htable.insert(keys[i], &vec_chars[i]); } // print our some hash tables // if (level_a >= Integral::ALL) { write_str_htable.debug(L"write_str_htable"); } // write the values // write_char_htable.write(text_file, (long)0); write_char_htable.write(bin_file, (long)0); write_str_htable.write(text_file, (long)0); write_str_htable.write(bin_file, (long)0); write_vec_char_htable.write(text_file, (long)0); write_vec_char_htable.write(bin_file, (long)0); String hash_name(L"hash"); text_file.put(object_name, 0, -1); write_empty_hash.writeData(text_file, hash_name); l.writeData(text_file); bin_file.put(object_name, 0, write_empty_hash.sofSize() + l.sofSize()); write_empty_hash.writeData(bin_file, hash_name); l.writeData(bin_file); text_file.put(object_name, 1, -1); write_nested_hash.writeData(text_file, hash_name); l.writeData(text_file); bin_file.put(object_name, 1, write_empty_hash.sofSize() + l.sofSize()); write_nested_hash.writeData(bin_file, hash_name); l.writeData(bin_file); // close the files // text_file.close(); bin_file.close(); // open the files in read mode // text_file.open(text_filename); bin_file.open(bin_filename); // create objects for reading in // HashTable read_char_htable_text; HashTable read_char_htable_bin; HashTable read_str_htable_text; HashTable read_str_htable_bin; HashTable< String, Vector > read_vec_char_htable_text; HashTable< String, Vector > read_vec_char_htable_bin; HashTable read_empty_text; HashTable read_empty_bin; // read in the hash tables and test for equivalence // if there is error, print out the hash tables // if (!read_char_htable_text.read(text_file, (long)0) || (read_char_htable_text.ne(write_char_htable))) { write_char_htable.debug(L"write_char_htable"); read_char_htable_text.debug(L"read_char_htable_text"); return Error::handle(name(), L"read char text", Error::TEST, __FILE__, __LINE__); } if (!read_char_htable_bin.read(bin_file, (long)0) || (read_char_htable_bin.ne(write_char_htable))) { write_char_htable.debug(L"write_char_htable"); read_char_htable_bin.debug(L"read_char_htable_bin"); return Error::handle(name(), L"read char bin", Error::TEST, __FILE__, __LINE__); } if (!read_str_htable_text.read(text_file, (long)0) || (read_str_htable_text.ne(write_str_htable))) { write_str_htable.debug(L"write_str_htable"); read_str_htable_text.debug(L"read_str_htable_text"); return Error::handle(name(), L"read str text", Error::TEST, __FILE__, __LINE__); } if (!read_str_htable_bin.read(bin_file, (long)0) || (read_str_htable_bin.ne(write_str_htable))) { write_str_htable.debug(L"write_str_htable"); read_str_htable_bin.debug(L"read_str_htable_bin"); return Error::handle(name(), L"read str bin", Error::TEST, __FILE__, __LINE__); } if (!read_vec_char_htable_text.read(text_file, (long)0) || (read_vec_char_htable_text.ne(write_vec_char_htable))) { write_vec_char_htable.debug(L"write_vec_char_htable"); read_vec_char_htable_text.debug(L"read_vec_char_htable_text"); return Error::handle(name(), L"read vec_char text", Error::TEST, __FILE__, __LINE__); } if (!read_vec_char_htable_bin.read(bin_file, (long)0) || (read_vec_char_htable_bin.ne(write_vec_char_htable))) { write_vec_char_htable.debug(L"write_vec_char_htable"); read_vec_char_htable_bin.debug(L"read_vec_char_htable_bin"); return Error::handle(name(), L"read vec_char bin", Error::TEST, __FILE__, __LINE__); } SofParser parser; if (!text_file.find(object_name, 0)) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } parser.load(text_file); if ((!read_empty_text.readData(text_file, hash_name, parser.getEntry(text_file, hash_name), false, true)) || (read_empty_text.ne(write_empty_hash))) { read_empty_text.debug(L"read_empty_text"); write_empty_hash.debug(L"write_empty_hash"); return Error::handle(name(), L"read empty text", Error::TEST, __FILE__, __LINE__); } Long read_l; if (!read_l.readData(text_file, Long::DEF_PARAM, parser.getEntry(text_file, Long::DEF_PARAM)) || read_l.ne(l)) { return Error::handle(name(), L"read empty text", Error::TEST, __FILE__, __LINE__); } if (!text_file.find(object_name, 1)) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } parser.reset(); parser.load(text_file); if ((!read_empty_text.readData(text_file, hash_name, parser.getEntry(text_file, hash_name), false, true)) || (read_empty_text.ne(write_nested_hash))) { read_empty_text.debug(L"read_nested_text"); write_nested_hash.debug(L"write_nested_hash"); return Error::handle(name(), L"read empty text", Error::TEST, __FILE__, __LINE__); } if (!read_l.readData(text_file, Long::DEF_PARAM, parser.getEntry(text_file, Long::DEF_PARAM)) || read_l.ne(l)) { return Error::handle(name(), L"read empty text", Error::TEST, __FILE__, __LINE__); } if (!bin_file.find(object_name, 0)) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } if ((!read_empty_bin.readData(bin_file, hash_name)) || (read_empty_bin.ne(write_empty_hash))) { read_empty_bin.debug(L"read_empty_bin"); write_empty_hash.debug(L"write_empty_hash"); return Error::handle(name(), L"read empty bin", Error::TEST, __FILE__, __LINE__); } if (!read_l.readData(bin_file) || read_l.ne(l)) { return Error::handle(name(), L"read empty bin ", Error::TEST, __FILE__, __LINE__); } if (!bin_file.find(object_name, 1)) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } if ((!read_empty_bin.readData(bin_file, hash_name)) || (read_empty_bin.ne(write_nested_hash))) { read_empty_bin.debug(L"read_nested_bin"); write_nested_hash.debug(L"write_nested_hash"); return Error::handle(name(), L"read empty bin", Error::TEST, __FILE__, __LINE__); } if (!read_l.readData(bin_file, Long::DEF_PARAM) || read_l.ne(l)) { return Error::handle(name(), L"read empty bin", Error::TEST, __FILE__, __LINE__); } // close and delete the temporary files // text_file.close(); bin_file.close(); // cleanup the memory that was created by the HashTable read // for ( long i = 0; i < 10; i++) { delete write_chars[i]; delete write_strings[i]; } delete [] write_chars; delete [] write_strings; delete [] vec_chars; // test equality methods // HashTable char_ht_0(SYSTEM, (long)50); // initialize the characters and store them in the htables // for (long i = 0; i < num_elem; i++) { // add the character to the hash table // char_ht_0.insert(keys[i], items[i]); } // create another hash table the same as this // HashTable char_ht_1; char_ht_1.assign(char_ht_0); if (char_ht_0.getAllocationMode() != char_ht_1.getAllocationMode()) { return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__); } if (!char_ht_0.eq(char_ht_1)) { char_ht_0.debug(L"char_ht_0"); char_ht_1.debug(L"char_ht_1"); return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__); } if (char_ht_0.ne(char_ht_1)) { return Error::handle(name(), L"ne", Error::TEST, __FILE__, __LINE__); } // test equality methods // HashTable char_ht_2(USER, (long)30); // initialize the characters and store them in the htables // for (long i = 0; i < num_elem; i++) { // add the character to the hash table // char_ht_2.insert(keys[i], items[i]); } // create another hash table the same as this // HashTable char_ht_3; char_ht_3.assign(char_ht_2); if (char_ht_3.getAllocationMode() != char_ht_2.getAllocationMode()) { return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__); } if (!char_ht_2.eq(char_ht_3)) { char_ht_2.debug(L"char_ht_2"); char_ht_3.debug(L"char_ht_3"); return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__); } if (char_ht_2.ne(char_ht_3)) { return Error::handle(name(), L"ne", Error::TEST, __FILE__, __LINE__); } // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } // -------------------------------------------------------------------- // // 2. testing class-specific public methods // hash table manipulation methods // // -------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing class-specific public methods: hash table manipulation methods...\n"); Console::increaseIndention(); } if (char_ht_0.getNumItems() != num_elem) { return Error::handle(name(), L"put", Error::TEST, __FILE__, __LINE__); } // get the character by its key // for (long i = 0; i < num_elem; i++) { Char* tmp_char = char_ht_0.get(keys[i]); if (tmp_char->ne(*items[i])) { tmp_char->debug(L"get char"); items[i]->debug(L"items[i]"); return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } if (char_ht_2.getNumItems() != num_elem) { return Error::handle(name(), L"put", Error::TEST, __FILE__, __LINE__); } // get the character by its key // for (long i = 0; i < num_elem; i++) { Char* tmp_char = char_ht_2.get(keys[i]); if (tmp_char->ne(*items[i])) { tmp_char->debug(L"get char"); items[i]->debug(L"items[i]"); return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } // -------------------------------------------------------------------- // // 3. testing class-specific public methods // hash table data access methods // // -------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing class-specific public methods: hash table data access methods...\n"); Console::increaseIndention(); } // get all the keys (SYSTEM mode) // Vector keys_list; char_ht_0.keys(keys_list); long index; if (keys_list.length() != num_elem) { return Error::handle(name(), L"keys", Error::TEST, __FILE__, __LINE__); } // check if we have got all the keys // for (long i = 0; i < num_elem; i++) { if (!keys_list.contains(index, &keys[i])) { return Error::handle(name(), L"keys", Error::TEST, __FILE__, __LINE__); } } // get all the keys (USER mode) // char_ht_2.keys(keys_list); if (keys_list.length() != num_elem) { return Error::handle(name(), L"keys", Error::TEST, __FILE__, __LINE__); } // check if we have got all the keys // for (long i = 0; i < num_elem; i++) { if (!keys_list.contains(index, &keys[i])) { return Error::handle(name(), L"keys", Error::TEST, __FILE__, __LINE__); } } // get all the values (SYSTEM mode) // Vector chars_list; char_ht_0.values(chars_list); if (chars_list.length() != num_elem) { return Error::handle(name(), L"values", Error::TEST, __FILE__, __LINE__); } // check if we have get all the values // for (long i = 0; i < num_elem; i++) { if (!chars_list.contains(index, items[i])) { return Error::handle(name(), L"values", Error::TEST, __FILE__, __LINE__); } } // get all the values (USER mode) // char_ht_2.values(chars_list); if (chars_list.length() != num_elem) { return Error::handle(name(), L"values", Error::TEST, __FILE__, __LINE__); } // check if we have get all the values // for (long i = 0; i < num_elem; i++) { if (!chars_list.contains(index, items[i])) { return Error::handle(name(), L"values", Error::TEST, __FILE__, __LINE__); } } // test contains (SYSTEM) // for (long i = 0; i < num_elem; i++) { if (!char_ht_0.containsKey(keys[i])) { keys[i].debug(L"this key is not found"); return Error::handle(name(), L"containsKey", Error::TEST, __FILE__, __LINE__); } if (!char_ht_0.containsValue(items[i])) { items[i]->debug(L"this value is not found"); return Error::handle(name(), L"containsValue", Error::TEST, __FILE__, __LINE__); } } // test contains (USER) // for (long i = 0; i < num_elem; i++) { if (!char_ht_2.containsKey(keys[i])) { keys[i].debug(L"this key is not found"); return Error::handle(name(), L"containsKey", Error::TEST, __FILE__, __LINE__); } if (!char_ht_2.containsValue(items[i])) { items[i]->debug(L"this value is not found"); return Error::handle(name(), L"containsValue", Error::TEST, __FILE__, __LINE__); } } // test remove (SYSTEM) // Char* char_ptr = new Char(); char_ht_0.remove(keys[0], char_ptr); if (char_ptr->ne(*items[0])) { return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__); } if (char_ht_0.containsKey(keys[0])) { return Error::handle(name(), L"remove / containsKey", Error::TEST, __FILE__, __LINE__); } if (char_ht_0.containsValue(items[0])) { return Error::handle(name(), L"remove / containsValue", Error::TEST, __FILE__, __LINE__); } delete char_ptr; char_ht_0.remove(keys[1]); if (char_ht_0.containsKey(keys[1])) { return Error::handle(name(), L"remove / containsKey", Error::TEST, __FILE__, __LINE__); } if (char_ht_0.containsValue(items[1])) { return Error::handle(name(), L"remove / containsValue", Error::TEST, __FILE__, __LINE__); } // test remove (USER) // char_ptr = (Char*)NULL; char_ht_2.remove(keys[0], char_ptr); if ((char_ptr == (Char*)NULL) || (char_ptr->ne(*items[0]))) { return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__); } if (char_ht_2.containsKey(keys[0])) { return Error::handle(name(), L"remove / containsKey", Error::TEST, __FILE__, __LINE__); } if (char_ht_2.containsValue(items[0])) { return Error::handle(name(), L"remove / containsValue", Error::TEST, __FILE__, __LINE__); } char_ht_2.remove(keys[1]); if (char_ht_2.containsKey(keys[1])) { return Error::handle(name(), L"remove / containsKey", Error::TEST, __FILE__, __LINE__); } if (char_ht_2.containsValue(items[1])) { return Error::handle(name(), L"remove / containsValue", Error::TEST, __FILE__, __LINE__); } // determine the occupancy of the htable (SYSTEM) // if (char_ht_0.isEmpty()) { return Error::handle(name(), L"isEmpty", Error::TEST, __FILE__, __LINE__); } // determine the occupancy of the htable (USER) // if (char_ht_2.isEmpty()) { return Error::handle(name(), L"isEmpty", Error::TEST, __FILE__, __LINE__); } // test clear (USER) -- first make a copy of char_ht_0 in system mode // char_ht_0.setAllocationMode(USER); char_ht_2.assign(char_ht_0); char_ht_0.setAllocationMode(SYSTEM); char_ht_2.clear(); if (!char_ht_2.isEmpty()) { return Error::handle(name(), L"clear", Error::TEST, __FILE__, __LINE__); } // test clear (SYSTEM) // char_ht_0.clear(); // create a hash table whose capacity* load_factor is less than 20 (SYSTEM) // HashTable tmp_htable_4(SYSTEM, (long)20); // put characters in the hash table // for (long i = 0; i < num_elem; i++) { // add the character to the htable // tmp_htable_4.insert(keys[i], items[i]); } // create a hash table whose capacity* load_factor is less than 20 (USER) // HashTable tmp_htable_7(USER, (long)20); tmp_htable_7.setLoadFactor(0.5); // put characters in the hash table // for (long i = 0; i < num_elem; i++) { // add the character to the htable // tmp_htable_7.insert(keys[i], items[i]); } // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } // -------------------------------------------------------------------- // // 4. testing class-specific public methods // hash table property methods // // -------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing class-specific public methods: hash table property methods...\n"); Console::increaseIndention(); } // the capacity should have be increased automatically // if (tmp_htable_4.getCapacity() != 40) { tmp_htable_4.debug(L"rehash tmp_htable_4"); return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } // check if all the keys are in the rehashed table // for (long i = 0; i < num_elem; i++) { if (!tmp_htable_4.containsKey(keys[i])) { return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } } // clear the table // tmp_htable_4.clear(); if (tmp_htable_4.getNumItems() != 0) { return Error::handle(name(), L"clear", Error::TEST, __FILE__, __LINE__); } // the capacity should have be increased automatically // if (tmp_htable_7.getCapacity() != 40) { tmp_htable_7.debug(L"rehash tmp_htable_7"); return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } // check if all the keys are in the rehashed table // for (long i = 0; i < num_elem; i++) { if (!tmp_htable_7.containsKey(keys[i])) { return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } } // clear the table // tmp_htable_7.clear(); if (tmp_htable_7.getNumItems() != 0) { return Error::handle(name(), L"clear", Error::TEST, __FILE__, __LINE__); } // preform some stress test on the hash table in SYSTEM mode // HashTable int_hash; long int_hash_size = 1000; for (long i = 0; i < int_hash_size; i++) { String key; key.assign(i); key.insert(L"key of ", 0); Long int_obj(i * 3); int_hash.insert(key, &int_obj); } // find out the maximum number of elements in one hash // double max = 0; for (long i = 0; i < int_hash.getCapacity(); i++) { max = Integral::max(max, (double)int_hash.table_d(i).length()); } // make sure that the maximum search length is two orders of // magnitude less than the number of elements // if (max > ((double)int_hash_size * 0.01)) { return Error::handle(name(), L"hash", Error::TEST, __FILE__, __LINE__); } // read the values back out of the hash // for (long i = 0; i < int_hash_size; i++) { String key; key.assign(i); key.insert(L"key of ", 0); if (!int_hash.get(key)->eq(i * 3)) { return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } // remove things from the hash and check that the size decreases // if (int_hash.getCapacity() != 2048) { return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } for (long i = 0; i < 850; i++) { String key; key.assign(i); key.insert(L"key of ", 0); if (!int_hash.remove(key)) { return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } if (int_hash.getCapacity() != 1024) { return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } for (long i = 850; i < 900; i++) { String key; key.assign(i); key.insert(L"key of ", 0); if (!int_hash.remove(key)) { return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } if (int_hash.getCapacity() != 512) { return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } for (long i = 900; i < 975; i++) { String key; key.assign(i); key.insert(L"key of ", 0); if (!int_hash.remove(key)) { return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } if (int_hash.getCapacity() != 128) { return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } for (long i = 975; i < 999; i++) { String key; key.assign(i); key.insert(L"key of ", 0); if (!int_hash.remove(key)) { return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } if (int_hash.getCapacity() != 128) { return Error::handle(name(), L"rehash", Error::TEST, __FILE__, __LINE__); } // preform some stress test on the hash table in USER mode // int_hash.clear(); int_hash.setCapacity(16); int_hash.setAllocationMode(USER); for (long i = 0; i < int_hash_size; i++) { String key; key.assign(i); key.insert(L"key of ", 0); Long* int_obj = new Long(i * 3); int_hash.insert(key, int_obj); } // read the values back out of the hash // for (long i = 0; i < int_hash_size; i++) { String key; key.assign(i); key.insert(L"key of ", 0); if (!int_hash.get(key)->eq(i * 3)) { return Error::handle(name(), L"get", Error::TEST, __FILE__, __LINE__); } } // cleanup the USER mode hashtable // int_hash.clear(Integral::FREE); // cleanUp // for (long i = 0; i < num_elem; i++) { delete items[i]; } delete [] items; delete [] keys; // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } //--------------------------------------------------------------------- // // 5. print completion message // //--------------------------------------------------------------------- // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } if (level_a > Integral::NONE) { SysString output(L"diagnostics passed for class "); output.concat(name()); output.concat(L"\n"); Console::put(output); } // exit gracefully // return true; } // end of include file // #endif