///////////////////////////////////////////////////////////////////////////// // unitTest_CppSemiExp.cpp - CppSemiExp Unit Tests // // ver 1.0 Uses testHarness module // // // // Language: Visual C++, ver 7.0 // // Platform: Dell Dimension 8300, Windows XP Prof, SP 1 // // Application: CSE687 prototype for project #1, Spring 2004 // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////////////// /* * Module Operations: * ================== * Provides a set of unit tests to validate CppSemiExp, using the * TestHarness module. * * Maintenance History: * ==================== * ver 1.0 : 24 Feb 04 * - first release * * Build Process: * ============== * Required Files: * CppSemiExp.h, CppSemiExp.cpp, CppToker.h, CppToker.cpp, * TestHarness.h, TestHarness.cpp, UnitTest_CppSemiExp.cpp * * Compiler Command: * cl /DUNITTEST_CPPSEMIEXP /EHsc \ * CppSemiExp.cpp CppToker.cpp TestHarness.cpp UnitTest_CppSemiExp.cpp */ // #ifdef UNITTEST_CPPSEMIEXP #include #include #include #include "CppSemiExp.h" #include "testharness.h" using namespace TestHarness; using namespace Scanner; /////////////////////////////////////////////////////////////////////// // test showToString() // class showToString : public test { public: showToString(output& out) : test(out) {} bool operator()() { title("showToString() function"); std::istringstream one("one\ntwo\nthree;"); CToker toker(&one); CSemiExp semi(&toker); while(semi.get()) tout << semi.showToString("",true); semi.get(); tout << semi.showToString("",true) << std::endl; return true; } }; /////////////////////////////////////////////////////////////////////// // test CppSemiExp construction, copy, assignment, destruction // class construction : public test { public: construction(output& out) : test(out) {} bool operator()() { title("CppSemiExp construction:"); try { CSemiExp orig; // default construction orig.push_back("one"); tout << " " << orig.showToString("orig: "); orig.push_back("two"); tout << " " << orig.showToString("orig: "); orig.insert(1,"three"); tout << " " << orig.showToString("orig: "); orig.push_back(";"); tout << " " << orig.showToString("orig: "); int i = static_cast(orig.find("three")); tout << " The index of token \"three\" is " << i << std::endl; tout << " -- construction passed --\n"; orig.get(); // does nothing since it has no CToker instance CSemiExp copy = orig; // copy construction tout << " " << copy.showToString("copy: "); tout << " -- copy construction passed --\n"; std::istringstream in("this is a semi-expression;"); CToker toker(&in); CSemiExp semi1(&toker); CSemiExp semi2(&toker); { semi2 = semi1; // test destruction of copy semi2.get(); tout << " " << semi2.showToString(); tout << " -- assignment passed --\n"; } in.clear(); in.seekg(0); semi1.get(); // if this succeeds, nested test passed tout << " " << semi1.showToString(); tout << " -- destruction passed --\n\n"; return true; } catch(exception e) { return false; } } }; // /////////////////////////////////////////////////////////////////////// // test copy constructing CppSemiExp instances in more than one scope // class nestedScope : public test { public: nestedScope(output& out) : test(out) {} bool operator()() { title("Nested Scope Fix"); std::istringstream inStr("int x; double y; char z;"); CToker tokA(&inStr); CSemiExp testA(&tokA); CCppCommentFilter CppCommFilter(&tokA); testA.registerFilter(&CppCommFilter); CCCommentFilter CCommFilter(&tokA); testA.registerFilter(&CCommFilter); CDoubleQuoteFilter CDoubleQF(&tokA); testA.registerFilter(&CDoubleQF); CSingleQuoteFilter CSingleQF(&tokA); testA.registerFilter(&CSingleQF); testA.get(); tout << " " << testA.showToString(); { CSemiExp testB(&tokA); CCppCommentFilter CppCommFilter(&tokA); testB.registerFilter(&CppCommFilter); CCCommentFilter CCommFilter(&tokA); testB.registerFilter(&CCommFilter); CDoubleQuoteFilter CDoubleQF(&tokA); testB.registerFilter(&CDoubleQF); CSingleQuoteFilter CSingleQF(&tokA); testB.registerFilter(&CSingleQF); testB = testA; testB.get(); tout << " " << testB.showToString(); } testA.get(); tout << " " << testA.showToString() << std::endl; return true; // if we get here test passed } }; /////////////////////////////////////////////////////////////////////// // Test CppSemiExp comment filter at end of file with no newline // - should return with no token // class commentAtEndOfStream : public test { public: commentAtEndOfStream(output& out) : test(out) {} bool operator()() { title("Comment at end of Stream Fix"); std::istringstream inStr1("a C comment follows /* a comment */"); CToker tok1(&inStr1); CSemiExp test1(&tok1); CCppCommentFilter CppCommFilter(&tok1); test1.registerFilter(&CppCommFilter); CCCommentFilter CCommFilter(&tok1); test1.registerFilter(&CCommFilter); CDoubleQuoteFilter CDoubleQF(&tok1); test1.registerFilter(&CDoubleQF); CSingleQuoteFilter CSingleQF(&tok1); test1.registerFilter(&CSingleQF); tout << " using comment filtering\n"; test1.get(); tout << test1.showToString(); std::istringstream inStr2("a C++ comment follows // a comment "); CToker tok2(&inStr2); CSemiExp test2(&tok2); CCppCommentFilter CppCommFilter2(&tok2); test2.registerFilter(&CppCommFilter2); CCCommentFilter CCommFilter2(&tok2); test2.registerFilter(&CCommFilter2); CDoubleQuoteFilter CDoubleQF2(&tok2); test2.registerFilter(&CDoubleQF2); CSingleQuoteFilter CSingleQF2(&tok2); test2.registerFilter(&CSingleQF2); test2.get(); tout << test2.showToString() << std::endl; return true; // if we get here test passed } }; // /////////////////////////////////////////////////////////////////////// // CppSemiExp Filters test // should remove C and C++ comments class filterSourceCode : public test { public: filterSourceCode(output& out) : test(out) {} bool findComment(const CSemiExp &semi) { for(int i=0; i<(int)semi.length(); i++) { if(semi[i].find("/*") < semi.length()) return true; if(semi[i].find("//") < semi.length()) return true; } return false; } bool operator()() { title("source code comment stripping in CppSemiExp"); std::string file = "..\\CppSemiExp.h"; std::ifstream in(file.c_str()); if(in.good()) { try { CToker toker(&in); CSemiExp semi(&toker); CCppCommentFilter CppCommFilter(&toker); semi.registerFilter(&CppCommFilter); CCCommentFilter CCommFilter(&toker); semi.registerFilter(&CCommFilter); CDoubleQuoteFilter CDoubleQF(&toker); semi.registerFilter(&CDoubleQF); CSingleQuoteFilter CSingleQF(&toker); semi.registerFilter(&CSingleQF); while(semi.get()) { tout << semi.showToString(); if(findComment(semi)) return false; } tout << semi.showToString() << std::endl; tout.write(); return true; } catch(exception e) { return false; } } return false; } }; // /////////////////////////////////////////////////////////////////////// // CppSemiExp construction and programmatic insertion of elements // class building : public test { public: building(output& out) : test(out) {} bool operator()() { title("manual construction of semi-expression"); CSemiExp test1; // default construction test1.push_back("one"); tout << " " << test1.showToString(); test1.push_back("two"); tout << " " << test1.showToString(); test1.insert(1,"three"); tout << " " << test1.showToString(); test1.push_back(";"); tout << " " << test1.showToString(); int i = static_cast(test1.find("three")); tout << " The index of token \"three\" is " << i << std::endl; test1.get(); // does nothing since it has no CToker instance tout << " " << test1.showToString() << std::endl; tout.write(); return true; // test is visual } }; /////////////////////////////////////////////////////////////////////// // test CppSemiExp copy construction // class copy : public test { public: copy(output& out) : test(out) {} bool operator()() { title("copy construction"); CSemiExp test1; // default construction test1.push_back("one"); test1.push_back("two"); test1.insert(1,"three"); test1.push_back(";"); tout << " " << test1.showToString(); CSemiExp test2 = test1; // compiler generated copy construction tout << " " << test2.showToString(); tout.write(); for(int i=0; i<(int)test1.length(); i++) if(test1[i] != test2[i]) return false; return true; } }; // /////////////////////////////////////////////////////////////////////// // test CppSemiExp assignment // class assign : public test { public: assign(output& out) : test(out) {} bool operator()() { title("assignment"); CSemiExp test1; // default construction test1.push_back("one"); test1.push_back("two"); test1.insert(1,"three"); test1.push_back(";"); tout << " " << test1.showToString(); CSemiExp test2; test2 = test1; // compiler generated assignment tout << " " << test2.showToString(); for(int i=0; i<(int)test1.length(); i++) if(test1[i] != test2[i]) return false; return true; } }; int main() { stdOutput out; tester t(out, "Testing CSemiExp Class"); nullOutput null; // null.showAll(true); t.registerTest(new showToString(null)); t.registerTest(new construction(null)); t.registerTest(new nestedScope(null)); t.registerTest(new commentAtEndOfStream(null)); t.registerTest(new filterSourceCode(null)); t.registerTest(new building(null)); t.registerTest(new copy(null)); t.registerTest(new assign(out)); t.execute(out); std::cout << "\n\n"; } #endif