// file: $isip/class/dstr/Set/SetDiagnose.h // version: $Id: SetDiagnose.h 10636 2007-01-26 22:18:09Z tm334 $ // // make sure definitions are made only once // #ifndef ISIP_DOUBLE_LINKED_LIST_DIAGNOSE #define ISIP_DOUBLE_LINKED_LIST_DIAGNOSE // isip include files // #ifndef ISIP_DOUBLE_LINKED_LIST #include "Set.h" #endif // SetDiagnose: a class that contains the diagnose method // of Set class. // template class SetDiagnose : public Set { //--------------------------------------------------------------------------- // // 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 Set::name(); } // other static methods // static bool8 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 SetDiagnose template class // //---------------------------------------------------------------------- // // required static methods // //---------------------------------------------------------------------- // method: diagnose // // arguments: // Integral::DEBUG level: (input) debug level for diagnostics // // return: a bool8 value indicating status // template bool8 SetDiagnose::diagnose(Integral::DEBUG level_a) { //---------------------------------------------------------------------- // // 0. preliminaries // //---------------------------------------------------------------------- // output the class name // if (level_a > Integral::NONE) { SysString output(L"diagnosing class "); output.concat(Set::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 // Set::setDebug(Set::debug_level_d); if (level_a > Integral::BRIEF) { Integral::debug(L"debug"); } // prepare items for all the lists used in this diagnose // int32 num_elem = 9; Char** items = new Char*[num_elem]; for (int32 i = 0; i < 3; i++) { for (int32 j = 0; j < 3; j++) { items[i * 3 + j] = new Char((unichar)((int32)'a' + j * 3 + (2 - i))); } } // test constructors and memory management // Set def_list; for (int32 i = 0; i < 9; i++) { def_list.insert(items[i]); } // copy constructor // Set copy_list(def_list); // the two constructed lists should have the same items in the nodes now // if (def_list.ne(copy_list)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // print out the list // if (level_a >= Integral::ALL) { def_list.debug(L"def_list"); } // check the constructors and destructors for allocating on the dynamic // memory heap // Set* def_dyn_list = new Set; def_dyn_list->assign(def_list); Set* copy_dyn_list = new Set(*def_dyn_list); // the two constructed lists should have the same items in their nodes now // if (def_dyn_list->ne(copy_list)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // see if we can dynamically delete // delete def_dyn_list; delete copy_dyn_list; // when memory is USER-allocated // // check the constructors for allocating on the stack // Set def_list_2; def_list_2.setAllocationMode(DstrBase::USER); for (int32 i = 0; i < 9; i++) { def_list_2.insert(items[i]); } Set copy_list_2(def_list_2); // the two constructed lists should have the same items in the nodes now // if (def_list_2.ne(copy_list_2)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } if (def_list_2.getAllocationMode() != copy_list_2.getAllocationMode()) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // check the constructors and destructors for allocating on the dynamic // memory heap // Set* def_dyn_list_2 = new Set(DstrBase::USER); for (int32 i = 0; i < 9; i++) { def_dyn_list_2->insert(items[i]); } Set* copy_dyn_list_2 = new Set(*def_dyn_list_2); // the two constructed lists should have the same items in their nodes now // if (def_dyn_list_2->ne(copy_list_2)) { return Error::handle(name(), L"copy constructor", Error::TEST, __FILE__, __LINE__); } // see if we can dynamically delete // delete def_dyn_list_2; delete copy_dyn_list_2; // test assign methods // Set tmp_list; Set* tmp_dyn_list = new Set(); Set tmp_list_1(DstrBase::USER); Set* tmp_dyn_list_1 = new Set(DstrBase::USER); // insert an item into the list // for (int32 i = 0; i < 9; i++) { tmp_list.insert(items[i]); tmp_list_1.insert(items[i]); } // try the list assign method // tmp_dyn_list->assign(tmp_list); tmp_dyn_list_1->assign(tmp_list_1); if (tmp_dyn_list->ne(tmp_list) || tmp_dyn_list->ne(tmp_list_1)) { return Error::handle(name(), L"list assign", Error::TEST, __FILE__, __LINE__); } if (tmp_dyn_list_1->ne(tmp_list) || tmp_dyn_list_1->ne(tmp_list_1)) { return Error::handle(name(), L"list assign", Error::TEST, __FILE__, __LINE__); } // clean up // delete tmp_dyn_list; delete tmp_dyn_list_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 lists // Char** write_chars = new Char*[5]; String** write_strings = new String*[5]; unichar tmp_char = L'a'; for (int32 j = 0; j < 5; j++) { write_chars[j] = new Char(tmp_char); write_strings[j] = new String(); 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"Set"); write_strings[4]->assign(L"String"); // create lists to write // Set write_null_list; Set write_char_list(DstrBase::USER); write_char_list.insert(write_chars[0]); Set write_str_list(DstrBase::USER); for (int32 i = 0; i < 5; i++) { write_str_list.insert(write_strings[i]); } // create objects for reading in, all read lists are SYSTEM-allocated // Set read_null_list_text; Set read_null_list_bin; Set read_char_list_text; Set read_char_list_bin; Set read_str_list_text; Set read_str_list_bin; // create items for writing // // write the values // write_null_list.write(text_file, (int32)11); write_null_list.write(bin_file, (int32)11); write_char_list.write(text_file, (int32)0); write_char_list.write(bin_file, (int32)0); write_str_list.write(text_file, (int32)0); write_str_list.write(bin_file, (int32)0); // 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); // read in the lists and test for equivalence // if there is error, print out the lists // if (!read_null_list_text.read(text_file, (int32)11) || (read_null_list_text.ne(write_null_list))) { read_null_list_text.debug(L"read_null_list_text"); return Error::handle(name(), L"read null text", Error::TEST, __FILE__, __LINE__); } if (!read_null_list_bin.read(bin_file, (int32)11) || (read_null_list_bin.ne(write_null_list))) { read_null_list_bin.debug(L"read_null_list_bin"); return Error::handle(name(), L"read null bin", Error::TEST, __FILE__, __LINE__); } if (!read_char_list_text.read(text_file, (int32)0) || (read_char_list_text.ne(write_char_list))) { read_char_list_text.debug(L"read_char_list_text"); return Error::handle(name(), L"read char text", Error::TEST, __FILE__, __LINE__); } if (!read_char_list_bin.read(bin_file, (int32)0) || (read_char_list_bin.ne(write_char_list))) { read_char_list_bin.debug(L"read_char_list_bin"); return Error::handle(name(), L"write char bin", Error::TEST, __FILE__, __LINE__); } if (!read_str_list_text.read(text_file, (int32)0) || (read_str_list_text.ne(write_str_list))) { read_str_list_text.debug(L"read_str_list_text"); return Error::handle(name(), L"read str text", Error::TEST, __FILE__, __LINE__); } if (!read_str_list_bin.read(bin_file, (int32)0) || (read_str_list_bin.ne(write_str_list))) { read_str_list_bin.debug(L"read_str_list_bin"); return Error::handle(name(), L"write str bin", Error::TEST, __FILE__, __LINE__); } // close and delete the temporary files // text_file.close(); bin_file.close(); File::remove(text_filename); File::remove(bin_filename); // clean the memory that was created by the Set read and write // read_char_list_text.clear(); read_char_list_bin.clear(); read_str_list_text.clear(); read_str_list_bin.clear(); for (int32 i = 0; i < 5; i++) { delete write_chars[i]; delete write_strings[i]; } delete [] write_chars; delete [] write_strings; // testing equality methods // Set* char_list = new Set; Char* characters = new Char[500]; unichar temp_char = L'a'; // initialize the characters and store them in the lists // for (int32 i = 0; i < 500; i++) { characters[i].assign(temp_char); // insert the character to the list // char_list->insert(&characters[i]); // increment the character value // temp_char++; } // self-allocated // Set* char_copy_list_1 = new Set(); char_copy_list_1->assign(*char_list); // not self-allocated // Set* char_copy_list_2 = new Set(DstrBase::USER); char_copy_list_2->assign(*char_list); // char_copy_list_1 and char_copy_list_2 should be the same as the // char_list // if (!char_list->eq(*char_copy_list_1)) { return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__); } if (char_list->ne(*char_copy_list_1)) { return Error::handle(name(), L"ne", Error::TEST, __FILE__, __LINE__); } if (!char_list->eq(*char_copy_list_2)) { return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__); } if (char_list->ne(*char_copy_list_2)) { return Error::handle(name(), L"ne", Error::TEST, __FILE__, __LINE__); } // clean up // delete char_list; delete char_copy_list_1; delete char_copy_list_2; delete [] characters; // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } // -------------------------------------------------------------------- // // 2. class-specific public methods: // positioning methods // // -------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing class-specific public methods: positioning methods...\n"); Console::increaseIndention(); } // test positioning, node and data accessing methods // Set tmp_list_2; for (int32 i = 0; i < 9; i++) { tmp_list_2.insert(items[i]); } // goto the first node // if (!tmp_list_2.gotoFirst()) { return Error::handle(name(), L"gotoFirst", Error::TEST, __FILE__, __LINE__); } // make sure this is the first node // if (!tmp_list_2.isFirst()) { return Error::handle(name(), L"isFirst", Error::TEST, __FILE__, __LINE__); } // make sure this is not the last node // if (tmp_list_2.isLast()) { return Error::handle(name(), L"isLast", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.first_d->getItem()->ne(*items[6]) || tmp_list_2.curr_d->getItem()->ne(*items[6])) { return Error::handle(name(), L"gotoFirst", Error::TEST, __FILE__, __LINE__); } // goto the next node // if (!tmp_list_2.gotoNext()) { return Error::handle(name(), L"gotoNext", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.curr_d->getItem()->ne(*items[3])) { return Error::handle(name(), L"gotoNext", Error::TEST, __FILE__, __LINE__); } // is mark_d set? // if (tmp_list_2.markIsSet()) { return Error::handle(name(), L"markIsSet", Error::TEST, __FILE__, __LINE__); } // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } //-------------------------------------------------------------------------- // // 3. class-specific public methods: // marking methods // //-------------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing class-specific public methods: marking methods...\n"); Console::increaseIndention(); } // set a mark here - the second node // tmp_list_2.setMark(); if (tmp_list_2.mark_d->getItem()->ne(*items[3])) { return Error::handle(name(), L"setMark", Error::TEST, __FILE__, __LINE__); } if (!tmp_list_2.isMarkedElement()) { return Error::handle(name(), L"isMarkedElement", Error::TEST, __FILE__, __LINE__); } if (!tmp_list_2.markIsSet()) { return Error::handle(name(), L"markIsSet", Error::TEST, __FILE__, __LINE__); } // goto the last node // if (!tmp_list_2.gotoLast()) { return Error::handle(name(), L"gotoLast", Error::TEST, __FILE__, __LINE__); } // make sure this is not the first node // if (tmp_list_2.isFirst()) { return Error::handle(name(), L"isFirst", Error::TEST, __FILE__, __LINE__); } // make sure this is the last node // if (!tmp_list_2.isLast()) { return Error::handle(name(), L"isLast", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.last_d->getItem()->ne(*items[2]) || tmp_list_2.curr_d->getItem()->ne(*items[2])) { return Error::handle(name(), L"gotoLast", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.isMarkedElement()) { return Error::handle(name(), L"isMarkedElement", Error::TEST, __FILE__, __LINE__); } // when there is no next node, gotoNext should stay at the current position // and return false // tmp_list_2.gotoLast(); if (tmp_list_2.gotoNext()) { return Error::handle(name(), L"gotoNext", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.curr_d != tmp_list_2.last_d) { return Error::handle(name(), L"gotoNext", Error::TEST, __FILE__, __LINE__); } // goto the previous node // if (!tmp_list_2.gotoPrev()) { return Error::handle(name(), L"gotoPrev", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.curr_d->getItem()->ne(*items[5])) { return Error::handle(name(), L"gotoPrev", Error::TEST, __FILE__, __LINE__); } // when there is no previous node, gotoPrev should stay at the current // position and return false // tmp_list_2.gotoFirst(); if (tmp_list_2.gotoPrev()) { return Error::handle(name(), L"gotoPrev", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.curr_d != tmp_list_2.first_d) { return Error::handle(name(), L"gotoPrev", Error::TEST, __FILE__, __LINE__); } // goto the marked node // if (!tmp_list_2.gotoMark()) { return Error::handle(name(), L"gotoMark", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.curr_d->getItem()->ne(*items[3]) || tmp_list_2.mark_d->getItem()->ne(*items[3])) { return Error::handle(name(), L"gotoMark", Error::TEST, __FILE__, __LINE__); } // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } //-------------------------------------------------------------------------- // // 4. class-specific public methods: // element access methods // //-------------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing class-specific public methods: element access methods...\n"); Console::increaseIndention(); } // get the element of the current node // if (tmp_list_2.getCurr()->ne(*items[3])) { return Error::handle(name(), L"getCurr", Error::TEST, __FILE__, __LINE__); } for (int32 i = 0; i < 9; i++) { Char x((int32)L'a' + i); if (tmp_list_2(i).ne(x)) { return Error::handle(name(), L"operator", Error::TEST, __FILE__, __LINE__); } } // test getPosition // if (tmp_list_2.getPosition() != 1) { return Error::handle(name(), L"getPosition", Error::TEST, __FILE__, __LINE__); } // test gotoPosition for all cases // for (int32 i = 0; i < 9; i++) { tmp_list_2.gotoPosition(i); if (tmp_list_2.getPosition() != i) { return Error::handle(name(), L"getPosition", Error::TEST, __FILE__, __LINE__); } } // test the contains method // tmp_list_2.gotoLast(); for (int32 i = 0; i < 9; i++) { if (!tmp_list_2.contains(items[i])) { return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__); } } tmp_list_2.gotoLast(); for (int32 i = 0; i < 9; i++) { if (!tmp_list_2.find(items[i])) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } if (tmp_list_2.getCurr()->ne(*items[i])) { return Error::handle(name(), L"getPosition", Error::TEST, __FILE__, __LINE__); } } // restore the position // tmp_list_2.gotoPosition(1); // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } //-------------------------------------------------------------------------- // // 5. class-specific public methods: // insert and remove methods // //-------------------------------------------------------------------------- // set indentation // if (level_a > Integral::NONE) { Console::put(L"testing class-specific public methods: insert and remove methods...\n"); Console::increaseIndention(); } // build a simple set // Set set_system(DstrBase::SYSTEM); Set set_user(DstrBase::USER); for (int32 i = 0; i < 9; i++) { if (!set_system.insert(items[i])) { return Error::handle(name(), L"insert", Error::TEST, __FILE__, __LINE__); } if (!set_user.insert(items[i])) { return Error::handle(name(), L"insert", Error::TEST, __FILE__, __LINE__); } } // now try to insert items again, it should fail // for (int32 i = 0; i < 9; i++) { if (set_system.insert(items[i])) { return Error::handle(name(), L"insert", Error::TEST, __FILE__, __LINE__); } if (set_user.insert(items[i])) { return Error::handle(name(), L"insert", Error::TEST, __FILE__, __LINE__); } } // find item[4] // if (!set_system.find(items[4])) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } if (!set_user.find(items[4])) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } // remove it // if (!set_system.remove()) { return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__); } if (!set_user.remove()) { return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__); } // make sure it is gone // if (set_system.contains(items[4])) { return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__); } if (set_user.contains(items[4])) { return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__); } Char* x; // find item[2] // if (!set_system.find(items[2])) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } if (!set_user.find(items[2])) { return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__); } // remove it: for system mode it should copy the object // x = new Char; if (!set_system.remove(x) || (x == items[2]) || x->ne(*items[2])) { return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__); } delete x; if (!set_user.remove(x) || (x != items[2])) { return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__); } // make sure it is gone // if (set_system.contains(items[2])) { return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__); } if (set_user.contains(items[2])) { return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__); } // make sure everything else is still there // for (int32 i = 0; i < 9; i++) { if ((i != 2) && (i != 4) && !set_system.contains(items[i])) { return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__); } if ((i != 2) && (i != 4) && !set_user.contains(items[i])) { return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__); } } // delete working data // for (int32 i = 0; i < 3; i++) { for (int32 j = 0; j < 3; j++) { delete items[i * 3 + j]; } } delete [] items; // reset indentation // if (level_a > Integral::NONE) { Console::decreaseIndention(); } //--------------------------------------------------------------------- // // 9. 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