#include #include #include "ut_string_class.h" #define DO_TEST(fn) \ fn(); \ puts(#fn) #define RT_TEST(e) if (!(e)) test_report_error(__FILE__, __LINE__, #e) #define RT_TEST_MSG(e,m) if (!(e)) test_report_error(__FILE__, __LINE__, #e, m) class UT_String_tester { public: static void test() { DO_TEST(test_construction); DO_TEST(test_copy_construction); DO_TEST(test_addition); DO_TEST(test_append); DO_TEST(test_add_self); DO_TEST(test_grow); DO_TEST(test_shrink); DO_TEST(test_substr); DO_TEST(test_swap); DO_TEST(test_collating); if (!m_nErrCount) { puts("All tests passed\n"); } else { printf("\n+++ Failed %d tests! +++\n\n", m_nErrCount); } } #undef DO_TEST private: static void test_report_error( const char* szFile, int nLine, const char* szExpression, const char* szMsg = 0) { if (szMsg) { printf("%s(%d): Failed test %s (%s)\n", szFile, nLine, szExpression, szMsg); } else { printf("%s(%d): Failed test %s\n", szFile, nLine, szExpression); } ++m_nErrCount; } static void assert_string_equality(const UT_String& s1, const UT_String& s2) { // Excercise comparison operators RT_TEST(s1 == s2); RT_TEST(s2 == s1); RT_TEST(s1.size() == s2.size()); RT_TEST(!(s1 != s2)); RT_TEST(((const char*)s1) == s2); RT_TEST(((const char*)s2) == s1); RT_TEST(s1 == ((const char*)s2)); RT_TEST(s2 == ((const char*)s1)); // If your compiler don't handle the following tests, just comment them // out. It's not like you'd encounter it in a real program. RT_TEST((s1.operator const char*()) == s2); RT_TEST((s2.operator const char*()) == s1); RT_TEST(s2 == (s1.operator const char*())); RT_TEST(s1 == (s2.operator const char*())); } static void test_construction() { const UT_String s1; // empty const UT_String s2; // empty const UT_String s3("foo"); RT_TEST(s1.size() == 0); RT_TEST(s2.size() == 0); RT_TEST(s1.empty()); RT_TEST(s2.empty()); RT_TEST(s3.size() == 3); assert_string_equality(s1, s2); assert_string_equality(s2, s1); RT_TEST(s1 == ""); RT_TEST(s2 == ""); RT_TEST(s3 == "foo"); RT_TEST(s3[0] == 'f'); RT_TEST(s3[1] == 'o'); RT_TEST(s3[2] == 'o'); RT_TEST(s3[3] == '\0'); const UT_String s4("foo", 2); RT_TEST(s4 == "fo"); RT_TEST(s4.size() == 2); const UT_String s5("foo\0\0", 5); RT_TEST(s5 == "foo"); RT_TEST(s5.size() != 3); } static void test_copy_construction() { const UT_String s2("foo"); const UT_String s4(s2); RT_TEST(s2.size() == 3); RT_TEST(s4.size() == 3); assert_string_equality(s2, s4); assert_string_equality(s4, s2); RT_TEST(s2 == "foo"); RT_TEST(s4 == "foo"); } static void test_addition() { const UT_String s1("foo"); const UT_String s2("bar1"); UT_String s3 = s1 + s2; UT_String s4 = s1 + "bar2"; RT_TEST(s3.size() == 7); RT_TEST(s4.size() == 7); RT_TEST(s3 == "foobar1"); RT_TEST(s4 == "foobar2"); } static void test_append() { UT_String s1("foo1"); UT_String s2("foo2"); const UT_String s3("bar2"); s1 += "bar1"; s2 += s3; const UT_String sRefStr1("foo1bar1"); const UT_String sRefStr2("foo2bar2"); RT_TEST(s1.size() == 8); RT_TEST(s2.size() == 8); RT_TEST(s1 == "foo1bar1"); RT_TEST(s2 == "foo2bar2"); assert_string_equality(s1, sRefStr1); assert_string_equality(s2, sRefStr2); } static void test_add_self() { UT_String s1("foo"); s1 += s1; // append with self RT_TEST(s1.size() == 6); RT_TEST(s1 == "foofoo"); s1 = s1 + s1; RT_TEST(s1.size() == 12); RT_TEST(s1 == "foofoofoofoo"); } static void test_grow() { UT_String s1("foo"); s1 += "1"; RT_TEST(s1.size() == 4); RT_TEST(s1 == "foo1"); s1 += "23"; RT_TEST(s1.size() == 6); RT_TEST(s1 == "foo123"); } static void test_shrink() { UT_String s1("foo123"); RT_TEST(s1.size() == 6); // silly RT_TEST(s1 == "foo123"); // silly s1 = "foo12"; RT_TEST(s1.size() == 5); RT_TEST(s1 == "foo12"); s1 = "foo"; RT_TEST(s1.size() == 3); RT_TEST(s1 == "foo"); s1 = ""; RT_TEST(s1.size() == 0); RT_TEST(s1 == ""); } static void test_substr() { UT_String s1("abcdefgh"); UT_String s2(s1.substr(0,100)); RT_TEST(s2 == "abcdefgh"); RT_TEST(s2.size() == 8); s2 = s1.substr(0,8); RT_TEST(s2 == "abcdefgh"); RT_TEST(s2.size() == 8); s2 = s1.substr(0,7); RT_TEST(s2 == "abcdefg"); RT_TEST(s2.size() == 7); s2 = s1.substr(0,1); RT_TEST(s2 == "a"); RT_TEST(s2.size() == 1); s2 = s1.substr(1,7); RT_TEST(s2 == "bcdefgh"); RT_TEST(s2.size() == 7); s2 = s1.substr(1,8); RT_TEST(s2 == "bcdefgh"); RT_TEST(s2.size() == 7); s2 = s1.substr(1,6); RT_TEST(s2 == "bcdefg"); RT_TEST(s2.size() == 6); s2 = s1.substr(1,1); RT_TEST(s2 == "b"); RT_TEST(s2.size() == 1); s2 = s1.substr(1,0); RT_TEST(s2 == ""); RT_TEST(s2.empty()); RT_TEST(s2.size() == 0); s2 = s1.substr(3,2); RT_TEST(s2 == "de"); RT_TEST(s2.size() == 2); s2 = s1.substr(3,5); RT_TEST(s2 == "defgh"); RT_TEST(s2.size() == 5); s2 = s1.substr(3,6); RT_TEST(s2 == "defgh"); RT_TEST(s2.size() == 5); s2 = s1.substr(3,7); RT_TEST(s2 == "defgh"); RT_TEST(s2.size() == 5); s2 = s1.substr(7,1); RT_TEST(s2 == "h"); RT_TEST(s2.size() == 1); s2 = s1.substr(7,2); RT_TEST(s2 == "h"); RT_TEST(s2.size() == 1); s2 = s1.substr(8,1); RT_TEST(s2 == ""); RT_TEST(s2.size() == 0); RT_TEST(s2.empty()); } static void test_swap() { UT_String s1("foo"); UT_String s2("bar"); s1.swap(s2); RT_TEST(s1 == "bar"); RT_TEST(s2 == "foo"); } static void test_collating() { UT_String s1("foo"); UT_String s2("bar"); RT_TEST(s2 < s1); s1 = "a"; s2 = "b"; RT_TEST(s1 < s2); s1 = "ab"; RT_TEST(s1 < s2); s1 = "a"; s2 = "a"; RT_TEST(!(s1 < s2)); s2 = "aa"; RT_TEST(s1 < s2); } static size_t m_nErrCount; }; size_t UT_String_tester::m_nErrCount = 0; int main() { UT_String_tester().test(); return 0; }