/* TestRational.cpp CIS 250 David Klick 2018-01-27 Test driver program for Rational class. */ #include "Rational.h" #include #include #include #include #include using std::boolalpha; using std::cerr; using std::cin; using std::cout; using std::endl; using std::invalid_argument; using std::streambuf; using std::string; using std::stringstream; int main(void) { int errors = 0; // Counts number of errors encountered int tests = 0; // Counts number of tests performed // Create array of Rational objects for testing Rational r[] = { Rational(), Rational(12,15), Rational(-15,-12), Rational(2, 3) }; // Basic tests: constructors, getNumerator, getDenominator tests++; if (r[3].getNumerator() != 2) { cout << "Rational(2, 3) or getNumerator() not working properly: " << r[3] << endl; errors++; } tests++; if (r[3].getDenominator() != 3) { cout << "Rational(2, 3) or getDenominator() not working properly: " << r[3] << endl; errors++; } tests++; if (r[0].getNumerator() != 1 || r[0].getDenominator() != 1) { cout << "Rational() not working properly: " << r[0] << endl; errors++; } tests++; if (r[0].getNumerator() != 1 || r[0].getDenominator() != 1) { cout << "Rational() not working properly: " << r[0] << endl; errors++; } tests++; if (r[1].getNumerator() != 4 || r[1].getDenominator() != 5) { cout << "Rational(12, 15) not working properly: " << r[1] << endl; errors++; } tests++; if (r[2].getNumerator() != 5 || r[2].getDenominator() != 4) { cout << "Rational(-15, -12) not working properly: " << r[2] << endl; errors++; } // Basic tests: setNums(int, int) tests++; r[0].setNums(210, 490); if (r[0].getNumerator() != 3 || r[0].getDenominator() != 7) { cout << "setnums(210, 490) not working properly: " << r[0] << endl; errors++; } tests++; r[0].setNums(0, 20); if (r[0].getNumerator() != 0 || r[0].getDenominator() != 1) { cout << "setnums(0, 20) not working properly: " << r[0] << endl; errors++; } tests++; r[0].setNums(-17, -13); if (r[0].getNumerator() != 17 || r[0].getDenominator() != 13) { cout << "setnums(-17, -13) not working properly: " << r[0] << endl; errors++; } // Test for setNums(int, int) throwing exception tests++; try { r[0].setNums(5, 0); cout << "setnums(5, 0) not throwing exception: " << r[0] << endl; errors++; } catch (invalid_argument e) { string msgShouldBe = string("Invalid rational number: 5/0"); string msgReceived = string(e.what()); if (msgShouldBe != msgReceived) { cout << "setnums(5, 0) exception message does not match" << endl; cout << " expected: " << msgShouldBe << endl; cout << " got: " << msgReceived << endl; errors++; } } // DisplayStle tests: getDisplayStyle, setDisplayStyle tests++; if (Rational::getDisplayStyle() != Rational::FRACTIONAL) { cout << "Display style not initialized correctly" << endl; errors++; } tests++; Rational::setDisplayStyle(Rational::FRACTIONAL); if (Rational::getDisplayStyle() != Rational::FRACTIONAL) { cout << "setDisplayStyle(FRACTIONAL) not working properly" << endl; errors++; } tests++; Rational::setDisplayStyle(Rational::FLOATING_POINT); if (Rational::getDisplayStyle() != Rational::FLOATING_POINT) { cout << "setDisplayStyle(FLOATING_POINT) not working properly" << endl; errors++; } // Insertion operator overload and displayStyle tests tests++; stringstream strTestStream; r[0].setNums(1, 8); strTestStream << r[0]; string strTest = strTestStream.str().substr(0, 5); if (strTest != string("0.125")) { cout << "Rational(1, 8) FLOATING_POINT display not working properly: " << strTest << endl; errors++; } tests++; Rational::setDisplayStyle(Rational::FRACTIONAL); strTestStream.str(""); strTestStream << r[0]; strTest = strTestStream.str(); if (strTest != string("1/8")) { cout << "Rational(1, 8) FRACTIONAL display not working properly: " << strTest << endl; errors++; } // Arithmetic tests: + - * / tests++; r[0].setNums(1, 2); r[1].setNums(1, 3); r[2] = r[0] + r[1]; if (r[0].getNumerator() != 1 || r[0].getDenominator() != 2 || r[1].getNumerator() != 1 || r[1].getDenominator() != 3 || r[2].getNumerator() != 5 || r[2].getDenominator() != 6) { cout << "+ overload not working properly: " << r[0] << " + " << r[1] << " => " << r[2] << endl; errors++; } tests++; r[0].setNums(1, 2); r[1].setNums(2, 3); r[2] = r[0] - r[1]; if (r[0].getNumerator() != 1 || r[0].getDenominator() != 2 || r[1].getNumerator() != 2 || r[1].getDenominator() != 3 || r[2].getNumerator() != -1 || r[2].getDenominator() != 6) { cout << "- overload not working properly: " << r[0] << " - " << r[1] << " => " << r[2] << endl; errors++; } tests++; r[0].setNums(1, 2); r[1].setNums(2, 3); r[2] = r[0] * r[1]; if (r[0].getNumerator() != 1 || r[0].getDenominator() != 2 || r[1].getNumerator() != 2 || r[1].getDenominator() != 3 || r[2].getNumerator() != 1 || r[2].getDenominator() != 3) { cout << "* overload not working properly: " << r[0] << " * " << r[1] << " => " << r[2] << endl; errors++; } tests++; r[0].setNums(2, 3); r[1].setNums(7, 33); r[2] = r[0] / r[1]; if (r[0].getNumerator() != 2 || r[0].getDenominator() != 3 || r[1].getNumerator() != 7 || r[1].getDenominator() != 33 || r[2].getNumerator() != 22 || r[2].getDenominator() != 7) { cout << "/ overload not working properly: " << r[0] << " / " << r[1] << " => " << r[2] << endl; errors++; } // Increment and decrement tests tests++; r[0].setNums(7, 8); r[1].setNums(7, 8); r[1]++; if (r[1].getNumerator() != 15 || r[1].getDenominator() != 8) { cout << "++ overload not working properly: " << r[0] << "++ => " << r[1] << endl; errors++; } tests++; r[0].setNums(7, 8); r[1].setNums(7, 8); r[1]--; if (r[1].getNumerator() != -1 || r[1].getDenominator() != 8) { cout << "-- overload not working properly: " << r[0] << "-- => " << r[1] << endl; errors++; } // Relational operator overload tests r[0].setNums(3, 8); r[1].setNums(2, 3); r[2].setNums(3, 8); tests++; if (r[0] == r[1] || !(r[0] == r[2])) { cout << "== overload not working properly: " << r[0] << ", " << r[1] << ", " << r[2] << endl; errors++; } tests++; if (r[0] != r[2] || !(r[0] != r[1])) { cout << "!= overload not working properly: " << r[0] << ", " << r[1] << ", " << r[2] << endl; errors++; } tests++; if (r[1] < r[0] || !(r[0] < r[1])) { cout << "< overload not working properly: " << r[0] << ", " << r[1] << ", " << r[2] << endl; errors++; } tests++; if (r[0] > r[1] || !(r[1] > r[0])) { cout << "> overload not working properly: " << r[0] << ", " << r[1] << ", " << r[2] << endl; errors++; } tests++; if (r[1] <= r[0] || !(r[0] <= r[1]) || !(r[0] <= r[2])) { cout << "<= overload not working properly: " << r[0] << ", " << r[1] << ", " << r[2] << endl; errors++; } tests++; if (r[0] >= r[1] || !(r[1] >= r[0]) || !(r[0] >= r[2])) { cout << ">= overload not working properly: " << r[0] << ", " << r[1] << ", " << r[2] << endl; errors++; } // Compound assignment/arithmetic tests r[0].setNums(3, 8); r[1].setNums(2, 3); r[0] += r[1]; tests++; if (r[0].getNumerator() != 25 || r[0].getDenominator() != 24 || r[1].getNumerator() != 2 || r[1].getDenominator() != 3) { cout << "+= overload not working properly: " << r[0] << ", " << r[1] << endl; errors++; } r[0].setNums(3, 8); r[1].setNums(2, 3); r[0] -= r[1]; tests++; if (r[0].getNumerator() != -7 || r[0].getDenominator() != 24 || r[1].getNumerator() != 2 || r[1].getDenominator() != 3) { cout << "-= overload not working properly: " << r[0] << ", " << r[1] << endl; errors++; } r[0].setNums(3, 8); r[1].setNums(2, 3); r[0] *= r[1]; tests++; if (r[0].getNumerator() != 1 || r[0].getDenominator() != 4 || r[1].getNumerator() != 2 || r[1].getDenominator() != 3) { cout << "*= overload not working properly: " << r[0] << ", " << r[1] << endl; errors++; } r[0].setNums(3, 8); r[1].setNums(2, 3); r[0] /= r[1]; tests++; if (r[0].getNumerator() != 9 || r[0].getDenominator() != 16 || r[1].getNumerator() != 2 || r[1].getDenominator() != 3) { cout << "/= overload not working properly: " << r[0] << ", " << r[1] << endl; errors++; } // Test of friend extraction operator overload // This redirects stdout temporarily to hide prompts stringstream inBuffer; stringstream myBuffer; streambuf *oldBuffer = cout.rdbuf(myBuffer.rdbuf()); inBuffer << "63\n9\n"; tests++; inBuffer >> r[0]; if (r[0].getNumerator() != 7 || r[0].getDenominator() != 1) { cout << ">> friend overload not working properly: " << r[0] << endl; errors++; } cout.rdbuf(oldBuffer); // Restore stdout // Finished with tests, so report results cout << tests << " tests attempted" << endl; cout << errors << " error" << (errors == 1 ? "" : "s") << " found by test program" << endl; // Return error status if any tests failed return errors == 0 ? 0 : 1; }