#include "Array.h" #include "Debug.h" #include "String.h" #include #include #include using std::cout; using std::endl; void useString() { cout << "\necci::String s1 = \"Jugador \";\n"; ecci::String s1 = "Jugador "; std::cout << "s1 = [" << s1 << "]\n"; cout << "\necci::String s2;\n"; ecci::String s2; std::cout << "s2 = [" << s2.c_str() << "]\n"; cout << "\nint i = 13;\ns2 = s1 + i;\n"; int i = 13; s2 = s1 + i; std::cout << "s2 = [" << s2 << "]\n"; cout << "\ns2 = s2\n"; s2 = s2; std::cout << "s2 = [" << s2 << "]\n"; cout << "\ns3 = i + s1;\n"; ecci::String s3 = i + s1; std::cout << "s3 = [" << s3 << "]\n"; // s3 += 1000 + ecci::String(" puntos"); } size_t testString() { // Counts the number of errors found size_t errors = 0; #if 0 // Default constructor ecci::String s1; ECCI_TEST2(errors, strlen(s1.c_str()) == 0, "Default constructor does not build an empty string" ); ECCI_TEST2(errors, s1.getLength() == 0, "getLength() does not report actual count after default constructor" ); // Conversion constructor const char* const cstr1 = "I <3 testing"; ecci::String s2 = cstr1; ECCI_TEST2(errors, s2.c_str() != cstr1, "Conversion constructor copies original C string address instead of duplicating" ); ECCI_TEST2(errors, strcmp(s2.c_str(), cstr1) == 0, "Conversion constructor does not replicated the original string" ); ECCI_TEST2(errors, s2.getLength() == strlen(cstr1), "getLength() does not report actual count after conversion constructor" ); // Capacity constructor ecci::String s3(1024); // Same as ecci::String s3{1024} ECCI_TEST2(errors, strlen(s3.c_str()) == 0, "Capacity constructor does not build an empty string" ); ECCI_TEST2(errors, s3.getLength() == 0, "getLength() does not report actual count after capacity constructor" ); // Copy constructor ecci::String s2c = s2; ECCI_TEST2(errors, s2c.c_str() != s2.c_str(), "Copy constructor copies original C string address instead of duplicating" ); ECCI_TEST2(errors, strcmp(s2c.c_str(), s2.c_str()) == 0, "Copy constructor does not duplicate other string" ); ECCI_TEST2(errors, s2c.getLength() == s2.getLength(), "getLength() does not report actual count after copy constructor" ); // Move constructor const char* cstr2 = s2c.c_str(); ecci::String s4 = std::move(s2c); ECCI_TEST2(errors, s4.c_str() == cstr2, "Move constructor does not move internal string from rvalue" ); ECCI_TEST2(errors, s2c.c_str() == nullptr, "Move constructor does not make null rvalue internal string" ); ECCI_TEST2(errors, s4.getLength() == strlen(cstr2), "Move constructor does not update count in lvalue" ); ECCI_TEST2(errors, s2c.getLength() == 0, "Move constructor does not update count in rvalue" ); // Copy assignment operator s2c = s2; ECCI_TEST2(errors, s2c.c_str() != s2.c_str(), "Copy assignment operator copies original C string address instead of duplicating" ); ECCI_TEST2(errors, strcmp(s2c.c_str(), s2.c_str()) == 0, "Copy assignment operator does not duplicate other string" ); ECCI_TEST2(errors, s2c.getLength() == s2.getLength(), "Copy assignment operator does not update count in lvalue" ); s2 = s2; ECCI_TEST2(errors, strcmp(s2c.c_str(), cstr1) == 0, "Copy assignment operator does not check if lvalue and rvalue are the same" ); // Move assignment operator cstr2 = s2c.c_str(); s4 = std::move(s2c); ECCI_TEST2(errors, s4.c_str() == cstr2, "Move ssignment operator does not move internal string from rvalue" ); ECCI_TEST2(errors, s2c.c_str() == nullptr, "Move ssignment operator does not make null rvalue internal string" ); ECCI_TEST2(errors, s4.getLength() == strlen(cstr2), "Move ssignment operator does not update count in lvalue" ); ECCI_TEST2(errors, s2c.getLength() == 0, "Move ssignment operator does not update count in rvalue" ); // Emptyness ECCI_TEST2(errors, s1.isEmpty(), "isEmpty() returns false for an empty string" ); ECCI_TEST2(errors, s2.isEmpty() == false, "isEmpty() returns true for a non empty string" ); ECCI_TEST2(errors, !s1 == true, "operator! returns false for an empty string" ); ECCI_TEST2(errors, !s2 == false, "operator! returns true for a non empty string" ); // Assignment operator from null terminated pointer string const char* const cstr3 = "Once the game is over the king and the pawn go back in the same box"; ecci::String s5; s5 = cstr3; ECCI_TEST2(errors, s5.c_str() != cstr3, "C-string assignment operator copies original C string address instead of duplicating" ); ECCI_TEST2(errors, strcmp(s5.c_str(), cstr3) == 0, "C-string assignment operator does not duplicate other string" ); ECCI_TEST2(errors, s5.getLength() == strlen(cstr3), "C-string assignment operator does not update count in lvalue" ); // Conversion operator to null terminated pointer string // Disabled test due to dangerous effects of conversion operators //ECCI_TEST2(errors, strcmp(s5, cstr3) == 0, "Conversion operator to C-string not working" ); // Character access ECCI_TEST2(errors, s4[3] == cstr2[3], "Non constant operator[] gives a not expected character" ); ECCI_TEST2(errors, &s4[3] == &cstr2[3], "Non constant operator[] gives a copy of the char instead of a reference to it" ); const ecci::String& s4cr = s4; ECCI_TEST2(errors, s4cr[3] == cstr2[3], "Constant operator[] gives a not expected character" ); ECCI_TEST2(errors, &s4cr[3] == &cstr2[3], "Constant operator[] gives a copy of the char instead of a reference to it" ); s4[3] = '8'; ECCI_TEST2(errors, s4[3] == '8', "Non constant operator[] must change character after assignment" ); // Substrings ECCI_TEST2(errors, strcmp(s5.substr(9,12).c_str(), "game is over") == 0, "substr() does not give the expected sub-string" ); ECCI_TEST2(errors, strcmp(s5.substr(64).c_str(), "box") == 0, "substr() wrong use of default parameter for count" ); ECCI_TEST2(errors, strcmp(s5.substr(64, 10).c_str(), "box") == 0, "substr() does not give remaining string if count is larger" ); ECCI_TEST2(errors, strcmp(s5.substr(94, 2).c_str(), "") == 0, "substr() must return empty string if pos is not valid" ); // Operator() ECCI_TEST2(errors, strcmp(s5(9,12).c_str(), "game is over") == 0, "operator() does not give the expected sub-string" ); ECCI_TEST2(errors, strcmp(s5(64, 10).c_str(), "box") == 0, "operator() does not give remaining string if count is larger" ); ECCI_TEST2(errors, strcmp(s5(94, 2).c_str(), "") == 0, "operator() must return empty string if pos is not valid" ); // Concatenation ecci::String s6{"abc"}; ECCI_TEST2(errors, strcmp((s6 + 'd').c_str(), "abcd") == 0, "Wrong operator+: String + char" ); ECCI_TEST2(errors, strcmp(('Z' + s6).c_str(), "Zabc") == 0, "Wrong operator+: char + String" ); ECCI_TEST2(errors, strcmp((s6 + 123ll).c_str(), "abc123") == 0, "Wrong operator+: String + long long" ); ECCI_TEST2(errors, strcmp((-123ll + s6).c_str(), "-123abc") == 0, "Wrong operator+: long long + String" ); ECCI_TEST2(errors, strcmp((s6 + 123llu).c_str(), "abc123") == 0, "Wrong operator+: String + unsigned long long" ); ECCI_TEST2(errors, strcmp(((unsigned long long)-1 + s6).c_str(), "18446744073709551615abc") == 0, "Wrong operator+: usigned long long + String" ); ECCI_TEST2(errors, strcmp((s6 + 3.14).c_str(), "abc3.140000") == 0, "Wrong operator+: String + double" ); ECCI_TEST2(errors, strcmp((-0.1 + s6).c_str(), "-0.100000abc") == 0, "Wrong operator+: double + String" ); ECCI_TEST2(errors, strcmp((s6 + "def").c_str(), "abcdef") == 0, "Wrong operator+: String + const char*" ); ECCI_TEST2(errors, strcmp(("XYZ" + s6).c_str(), "XYZabc") == 0, "Wrong operator+: const char* + String" ); ECCI_TEST2(errors, strcmp((s2 + s6).c_str(), "I <3 testingabc") == 0, "Wrong operator+: String + String" ); ECCI_TEST2(errors, strcmp((s2 + ' ' + s6 + -0123 + "!!").c_str(), "I <3 testing abc-83!!") == 0, "Wrong operator+: String + String" ); // Equality ecci::String s7{"f"}; ECCI_TEST2(errors, s7 == 'f', "operator==: String == char returns false for equal chars" ); ECCI_TEST2(errors, !(s7 == 'g'), "operator==: String == char returns true for different chars" ); ECCI_TEST2(errors, !(s6 == 'a'), "operator==: String == char returns true for strings of different count starting with same letter" ); ECCI_TEST2(errors, 'f' == s7, "operator==: char == String returns false for equal chars" ); ECCI_TEST2(errors, !('g' == s7), "operator==: char == String returns true for different chars" ); ECCI_TEST2(errors, !('a' == s6), "operator==: char == String returns true for strings of different count starting with same letter" ); ECCI_TEST2(errors, s6 == "abc", "operator==: String == cstr returns false for equal chars" ); ECCI_TEST2(errors, !(s6 == "ab"), "operator==: String == cstr returns true for different strings" ); ECCI_TEST2(errors, "abc" == s6, "operator==: cstr == String returns false for equal chars" ); ECCI_TEST2(errors, !("ab" == s6), "operator==: cstr == String returns true for different strings" ); ecci::String s8("abc"); ECCI_TEST2(errors, s6 == s8, "operator==: String == String returns false for equal strings" ); ECCI_TEST2(errors, !(s6 == s7), "operator==: String == String returns true for different strings" ); // Searching characters ECCI_TEST2(errors, s5.find('o') == 17, "find(ch) does not find the right position of an existing char" ); ECCI_TEST2(errors, s5.find('z') == ecci::String::npos, "find(ch) does find a non existing char" ); ECCI_TEST2(errors, s5.find('K') == ecci::String::npos, "find(ch) does find a non existing char in exact case" ); ECCI_TEST2(errors, s5.find('k', 31) == 50, "find(ch, start) does not find the right position of an existing char after a given position" ); ECCI_TEST2(errors, s5.find('k', 50) == 50, "find(ch, start) does not find a char found in the same starting position" ); ECCI_TEST2(errors, s5.find('k', 51) == ecci::String::npos, "find(ch, start) does find a non existing char after a given position" ); ECCI_TEST2(errors, s5.findNoCase('o') == 0, "findNoCase(ch) does not find the right position of an existing char" ); ECCI_TEST2(errors, s5.findNoCase('z') == ecci::String::npos, "findNoCase(ch) does find a non existing char" ); ECCI_TEST2(errors, s5.findNoCase('K', 31) == 50, "findNoCase(ch, start) does not find the right position of an existing char after given position" ); ECCI_TEST2(errors, s5.findNoCase('v', 20) == ecci::String::npos, "findNoCase(ch, start) does not find the right position of an existing char after given position" ); // Searching strings ECCI_TEST2(errors, s5.find("the") == 5, "find(cstr) does not find the right position of an existing string" ); ECCI_TEST2(errors, s5.find("the", 6) == 22, "find(cstr, start) does not find the right position of an existing string after given position" ); ECCI_TEST2(errors, s5.find("btw") == ecci::String::npos, "find(cstr) does find a non existing string" ); ECCI_TEST2(errors, s5.find("the", 56) == ecci::String::npos, "find(cstr, start) does find a non existing string after given position" ); ECCI_TEST2(errors, s5.findNoCase("The") == 5, "findNoCase(cstr) does not find the right position of an existing string" ); ECCI_TEST2(errors, s5.findNoCase("HE", 7) == 23, "findNoCase(cstr, start) does not find the right position of an existing string after given position" ); ECCI_TEST2(errors, s5.findNoCase("BtW") == ecci::String::npos, "findNoCase(cstr) does find a non existing string" ); ECCI_TEST2(errors, s5.findNoCase("The", 56) == ecci::String::npos, "findNoCase(cstr, start) does find a non existing string after given position" ); #endif // All tests finished return errors; } void testCopyIndependence(ecci::Array& copied, const ecci::Array& original, const char* methodName) { // Modify some elements in copy and test original remains unchanged for (size_t i = 0; i < copied.getCount(); ++i ) if ( i % 2 ) copied[i] += copied.getCount(); for (size_t i = 0; i < copied.getCount(); ++i ) if ( i % 2 ) ECCI_TEST(copied[i] != original[i], methodName << " did not produce independent arrays" ); else ECCI_TEST(copied[i] == original[i], methodName << ": unmodified elements in a copied array must remain unmodified" ); } size_t testArray() { // Counts the number of errors found size_t errors = 0; #if 0 const size_t testSize = 1024; // Default constructor ecci::Array a1; ECCI_TEST2(errors, a1.getCount() == 0, "getCount() does not report actual count after default constructor" ); // Add values to a1 and test them for (size_t i = 0; i < testSize; ++i ) a1.add(i % 2); for (size_t i = 0; i < testSize; ++i ) ECCI_TEST2(errors, a1[i] == i % 2, "Array did not store boolean " << i << " or operator[] is wrong" ); // Capacity constructor ecci::Array a2(testSize); // Same as ecci::Array s2{1024} ECCI_TEST2(errors, a2.getCount() == 0, "getCount() does not report actual count after capacity constructor" ); // Add counters to a2 (one more) and test them for (size_t i = 0; i < testSize + 1; ++i ) a2.add(i); for (size_t i = 0; i < testSize + 1; ++i ) ECCI_TEST2(errors, a2[i] == i, "Array did not store index " << i << " or operator[] is wrong" ); // The following assignment must not compile // If it compiles you have an implicit conversion constructor. Fix it, then comment the line a2 = 13; // Copy constructor ecci::Array a2c = a2; ECCI_TEST2(errors, a2c.getCount() == a2.getCount(), "getCount() does not report actual count after copy constructor" ); testCopyIndependence(a2c, a2, "Copy constructor"); // Move constructor ecci::Array a3 = std::move(a2c); ECCI_TEST2(errors, a3.getCount() == a2.getCount(), "Move constructor does not update count in lvalue" ); ECCI_TEST2(errors, a2c.getCount() == 0, "Move constructor does not update count in rvalue" ); // Copy assignment operator a2c = a2; ECCI_TEST2(errors, a2c.getCount() == a2.getCount(), "getCount() does not report actual count after copy assignment operator" ); testCopyIndependence(a2c, a2, "Copy assignment operator"); // Make sure your operator= avoids to destroy itself when user asks to overwrite itself a2 = a2; // Move assignment operator a3 = std::move(a2c); ECCI_TEST2(errors, a3.getCount() == a2.getCount(), "Move assignment operator does not update count in lvalue" ); ECCI_TEST2(errors, a2c.getCount() == 0, "Move assignment operator does not update count in rvalue" ); // Finding elements ecci::Array fib1; fib1.add(0); fib1.add(1); for (size_t i = 2; i < testSize + 2; ++i) fib1.add( fib1[i - 2] + fib1[i - 1] ); assert(testSize > 13); ECCI_TEST2(errors, fib1.find(13) == 7, "find() does not give the expected position of an existing element" ); ECCI_TEST2(errors, fib1.find(13, 8) == fib1.npos, "find() founds a non existing element after a start position" ); ECCI_TEST2(errors, fib1.find(-13) == ecci::Array::npos, "find() must return a non valid position for an inexistent element" ); ECCI_TEST2(errors, fib1.find(13, testSize + 1) == fib1.npos, "find() must return non valid position for non valid start index" ); // Inserting elements auto fib2 = fib1; fib1.insert(7, -13); ECCI_TEST2(errors, fib1[7] == -13, "insert() does not insert a value in the expected position" ); ECCI_TEST2(errors, fib1[8] == 13, "insert() does not shift values one position right" ); ECCI_TEST2(errors, fib1.getCount() == fib2.getCount() + 1, "insert() does not update count appropiately" ); // Equality auto fib3 = fib1; ECCI_TEST2(errors, fib3 == fib1, "operator== returns false for two equal arrays" ); ECCI_TEST2(errors, !(fib1 == fib2), "operator== returns true for two different arrays" ); ECCI_TEST2(errors, fib1 == fib1, "operator== returns false for the same array" ); // Appending ecci::Array fib0; fib0 << -2ll << -1ll; ECCI_TEST2(errors, fib0[0] == -2, "operator<< does not append a value" ); ECCI_TEST2(errors, fib0[1] == -1, "operator<< does not append a second value" ); ECCI_TEST2(errors, fib0.getCount() == 2, "operator<< does not update count" ); // Printing for ( size_t i = 0; i < 10; ++i ) fib0 << fib1[i]; cout << "fib0 = " << fib0 << std::endl; #endif // All tests finished return errors; } void printTestResult(size_t errorCount, const char* testName) { std::cout << testName << (errorCount == 0 ? "passed" : "failed" ) << std::endl; } void useArray(); void useList(); int main() { // useString(); // useArray(); useList(); // printTestResult( testString(), "String tests "); // printTestResult( testArray(), "Array tests "); } template void printArray(const char* description, const ecci::Array& arr) { cout << description; for ( size_t i = 0; i < arr.getCount(); ++i ) cout << i << ": " << arr[i] << endl; } void useArray() { ecci::Array arr1; arr1.add(-1.0); arr1.add(0.0); arr1.add(2.0); arr1.add(-3.14); for (size_t i = 0; i < 17; ++i ) arr1.add(i); arr1[13] = -13.0; printArray("arr1:\n", arr1); ecci::Array arr2; arr2.add("I <3 templates"); arr2.add("Me 2"); arr2.add("U2?"); printArray("\narr2:\n", arr2); // cout << arr; } #include "List.h" void useList() { ecci::List notas; for ( size_t i = 0; i < 10; ++i ) notas.add(i); //notas.print(); for ( ecci::List::Iterator itr = notas.begin(); itr != notas.end(); ++itr ) std::cout << '[' << *itr << ']'; ecci::List::Iterator itr = notas.find(-2); if ( itr != notas.end() ) notas.insert(itr, -4.0); std::cout << std::endl; }