///////////////////////////////////////////////////////////////////// // TestScanner.cpp - Automated testing of Scanner module // // ver 1.0 - /D TEST_WITHOUTCOMMENTS enables testing // // when comments are disabled (default) // // // // Language: C++, Visual Studio 2015 // // Application: Parser component, CSE687 - Object Oriented Design // // Author: Jim Fawcett, Syracuse University, CST 4-187 // // jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// /* * Package Operations: * ------------------- * TestScanner provides automated low-level testing of the Tokenizer * and SemiExp packages that are all the parts of a Scanner module. * * Build Process: * -------------- * Required Files: * TestScanner.cpp, SemiExp.h, SemiExp.cpp, Tokenizer.h, Tokenizer.cpp, * Utilities.h, Utilities.cpp * * Build Command: * devenv Scanner.sln /debug rebuild /D TEST_WITHOUTCOMMENTS * * Maintenence History: * --------------------- * ver 1.0 : 19 Feb 2016 * - released to class as Instructor's Solution for Project #1 */ #include "../SemiExp/itokcollection.h" #include "../SemiExp/SemiExp.h" #include "../Tokenizer/Tokenizer.h" #include "../Utilities/Utilities.h" #include #include #include using namespace Scanner; using Util = Utilities::StringHelper; ///////////////////////////////////////////////////////////////////// // TestScanner class provides template for automated testing // of scanner module class TestScanner { public: bool test(); private: bool testToker(); bool testSemi(); bool testSemiGet(); bool testSemiBuild(); }; //----< aggregate tests for Tokenizer and SemiExp >------------------ bool TestScanner::test() { bool p1 = testToker(); bool p2 = testSemi(); return p1 && p2; } //----< Tests simply tokenize a test file to demo requirements >----- bool TestScanner::testToker() { std::string fileSpec = "../Tokenizer/test3.txt"; std::ifstream in(fileSpec); if (!in.good()) { std::cout << "\n can't open " << fileSpec << "\n"; return false; } std::cout << "\n Processing file: " << fileSpec; std::string tok; #ifdef TEST_WITHOUTCOMMENTS Util::title("Testing Toker without comments"); Toker toker; toker.attach(&in); while (in.good()) { tok = toker.getTok(); if (tok == "\n") tok = "newline"; std::cout << "\n -- " << tok; } std::cout << "\n"; #endif Util::title("Testing toker with comments"); in.clear(); in.seekg(std::ios::beg); Toker toker2; toker2.attach(&in); toker2.returnComments(); while (in.good()) { tok = toker2.getTok(); if (tok == "\n") tok = "newline"; else std::cout << "\n -- " << tok; } std::cout << "\n\n"; return true; } //----< test file related SemiExp operations >----------------------- bool TestScanner::testSemiGet() { Util::title("testing get(), length(), trimFront()"); std::string fileSpec = "../SemiExp/Test1.txt"; std::ifstream in(fileSpec); if (!in.good()) { std::cout << "\n can't open " << fileSpec << "\n"; return false; } std::cout << "\n Processing file: " << fileSpec; Toker toker; toker.attach(&in); ITokCollection* pTC = new SemiExp(&toker); std::cout << "\n"; while (pTC->get()) { int lengthBeforeTrim = pTC->length(); pTC->trimFront(); int lengthAfterTrim = pTC->length(); std::cout << "\n --- SemiExpression ---"; std::cout << "\n length before trim: " << lengthBeforeTrim; std::cout << ", length after trim: " << lengthAfterTrim; std::cout << pTC->show(); } if (pTC->length() > 0) pTC->show(); return true; } //----< test SemiExp building operations >--------------------------- bool TestScanner::testSemiBuild() { Util::title("Testing building and accessing a SemiExp"); Utilities::putline(); Util::title("testing push_back"); SemiExp semi; ITokCollection* pTC = ; pTC->push_back("one"); pTC->push_back("two"); pTC->push_back("three"); std::cout << (pTC->show()); Util::title("testing indexing"); ITokCollection& tc = *pTC; for (size_t i = 0; i < tc.length(); ++i) std::cout << "\n -- " << tc[i]; Utilities::putline(); Util::title("testing find"); for (size_t i = 0; i < tc.length(); ++i) std::cout << "\n find(" << tc[i] << ") returns " << tc.find(tc[i]); Utilities::putline(); Util::title("calling remove(0)"); if(tc.remove(0)) std::cout << tc.show(); Util::title("calling remove(\"three\")"); if (tc.remove("three")) std::cout << tc.show(); Util::title("testing tolower"); tc.push_back("Abc"); tc.push_back("CDE"); std::cout << tc.show(); tc.toLower(); std::cout << tc.show(); Util::title("testing clear with a following push_back"); tc.clear(); tc.push_back("pushed_back"); std::cout << tc.show(); return true; } //----< aggregate testing functions for SemiExp >-------------------- bool TestScanner::testSemi() { Util::Title("Testing SemiExp", '='); std::cout << "\n"; bool p1 = testSemiGet(); bool p2 = testSemiBuild(); return p1 && p2; } //----< helper function avoids repetition of trivial I/O >----------- void checkTest(const std::string& name, bool predicate) { if (predicate) std::cout << "\n " << name << " passed"; else std::cout << "\n " << name << " failed"; } //----< test setup and execution >----------------------------------- int main() { Util::Title("Testing Scanner"); TestScanner ts; checkTest("Scanner Test", ts.test()); std::cout << "\n\n"; }