diff --git a/CMakeLists.txt b/CMakeLists.txt index 9aa51d6a3..4267e63be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,5 +154,5 @@ IF(EQEMU_BUILD_AZONE OR EQEMU_BUILD_CLEANIPC) ENDIF(EQEMU_BUILD_AZONE OR EQEMU_BUILD_CLEANIPC) IF(EQEMU_BUILD_TESTS) - #ADD_SUBDIRECTORY(tests) + ADD_SUBDIRECTORY(tests) ENDIF(EQEMU_BUILD_TESTS) diff --git a/LICENSE.md b/LICENSE.md index 09c333c99..ced7868b8 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -8,4 +8,4 @@ StackWalker - New BSD License ZLib - ZLib License MySQL - GPL Perl - GPL / ActiveState (under the assumption that this is a free project). -Google Test - New BSD License \ No newline at end of file +CPPUnit - GLP diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..f3a23212d --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,37 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +ADD_SUBDIRECTORY(cppunit) + +SET(tests_sources + main.cpp +) + +SET(tests_headers + memory_mapped_file_test.h + ipc_mutex_test.h + fixed_memory_test.h +) + +ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers}) + +TARGET_LINK_LIBRARIES(tests Common cppunit) + +IF(MSVC) + SET_TARGET_PROPERTIES(tests PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") + TARGET_LINK_LIBRARIES(tests "Ws2_32.lib") +ENDIF(MSVC) + +IF(MINGW) + TARGET_LINK_LIBRARIES(tests "WS2_32") +ENDIF(MINGW) + +IF(UNIX) + TARGET_LINK_LIBRARIES(tests "dl") + TARGET_LINK_LIBRARIES(tests "z") + TARGET_LINK_LIBRARIES(tests "m") + TARGET_LINK_LIBRARIES(tests "rt") + TARGET_LINK_LIBRARIES(tests "pthread") + ADD_DEFINITIONS(-fPIC) +ENDIF(UNIX) + +SET(EXECUTABLE_OUTPUT_PATH ../Bin) diff --git a/tests/cppunit/CMakeLists.txt b/tests/cppunit/CMakeLists.txt new file mode 100644 index 000000000..4ff178523 --- /dev/null +++ b/tests/cppunit/CMakeLists.txt @@ -0,0 +1,38 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(cppunit_sources + collectoroutput.cpp + compileroutput.cpp + htmloutput.cpp + missing.cpp + source.cpp + suite.cpp + textoutput.cpp + time.cpp + utils.cpp +) + +SET(cppunit_headers + cpptest-assert.h + cpptest-collectoroutput.h + cpptest-compileroutput.h + cpptest-htmloutput.h + cpptest-output.h + cpptest-source.h + cpptest-suite.h + cpptest-textoutput.h + cpptest-time.h + cpptest.h + missing.h + utils.h + winconfig.h +) + +ADD_LIBRARY(cppunit ${cppunit_sources} ${cppunit_headers}) + + +IF(UNIX) + ADD_DEFINITIONS(-fPIC) +ENDIF(UNIX) + +SET(LIBRARY_OUTPUT_PATH ../../Bin) diff --git a/tests/cppunit/collectoroutput.cpp b/tests/cppunit/collectoroutput.cpp new file mode 100644 index 000000000..1e2ffc204 --- /dev/null +++ b/tests/cppunit/collectoroutput.cpp @@ -0,0 +1,106 @@ +// --- +// +// $Id: collectoroutput.cpp,v 1.4 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +#include "cpptest-collectoroutput.h" + +using namespace std; + +namespace Test +{ + CollectorOutput::TestInfo::TestInfo(const string name) + : _name(name) + {} + + CollectorOutput::SuiteInfo::SuiteInfo(const string& name, int tests) + : _name(name), + _errors(0) + { + _tests.reserve(tests); + } + + /// Constructs a collector object. + /// + CollectorOutput::CollectorOutput() + : Output(), + _total_errors(0) + {} + + void + CollectorOutput::finished(int tests, const Time& time) + { + _total_tests = tests; + _total_time = time; + } + + void + CollectorOutput::suite_start(int tests, const string& name) + { + if (tests > 0) + { + _suites.push_back(SuiteInfo(name, tests)); + _cur_suite = &_suites.back(); + } + } + + void + CollectorOutput::suite_end(int tests, const string&, const Time& time) + { + if (tests > 0) + { + _cur_suite->_time = time; + _total_errors += _cur_suite->_errors; + } + } + + void + CollectorOutput::test_start(const string& name) + { + _cur_suite->_tests.push_back(TestInfo(name)); + _cur_test = &_cur_suite->_tests.back(); + } + + void + CollectorOutput::test_end(const string&, bool ok, const Time& time) + { + if (!(_cur_test->_success = ok)) + ++_cur_suite->_errors; + _cur_test->_time = time; + } + + void + CollectorOutput::assertment(const Source& s) + { + _cur_test->_sources.push_back(s); + } + +} // namespace Test + diff --git a/tests/cppunit/compileroutput.cpp b/tests/cppunit/compileroutput.cpp new file mode 100644 index 000000000..23eec3986 --- /dev/null +++ b/tests/cppunit/compileroutput.cpp @@ -0,0 +1,133 @@ +// --- +// +// $Id: compileroutput.cpp,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#include +#include + +#include "cpptest-compileroutput.h" +#include "cpptest-source.h" + +using namespace std; + +namespace Test +{ + namespace + { + // Checks for output format modifiers. + // + bool + check_format(const string& format, + string::size_type& pos, + const string& mod, + int& mod_cnt) + { + if (format.compare(pos, mod.size(), mod) == 0) + { + if (++mod_cnt > 1) + throw Test::CompilerOutput::InvalidFormat(format); + pos += mod.size(); + return true; + } + return false; + } + + } // anonymous namespace + + /// Constructs a compiler output handler. + /// + /// \param format Pre-defined compiler output format. + /// \param stream Stream to output to. + /// + CompilerOutput::CompilerOutput(Format format, ostream& stream) + : Output(), + _stream(stream) + { + static const char* table[] = + { + "%file:%line: %text", // Generic + "Error cpptest %file %line: %text", // BCC + "%file:%line: %text", // GCC + "%file(%line) : %text" // MSVC + }; + + _format = table[format]; + } + + /// Constructs a compiler output handler. + /// + /// \param format %Output format to use. + /// \param stream Stream to output to. + /// + /// \exception InvalidFormat Invalid format specified. + /// + CompilerOutput::CompilerOutput(const string& format, ostream& stream) + : Output(), + _format(format), + _stream(stream) + { + int expr(0), file(0), line(0); + + for (string::size_type pos = 0; + (pos = _format.find_first_of('%', pos)) != string::npos; ) + { + ++pos; + if (check_format(_format, pos, "expr", expr)) ; + else if (check_format(_format, pos, "file", file)) ; + else if (check_format(_format, pos, "line", line)) ; + else + throw InvalidFormat(format); + } + + if (!expr && !file && !line) + throw InvalidFormat(format); + } + + void + CompilerOutput::assertment(const Source& s) + { + string fmt(_format); + string::size_type pos; + + fmt.reserve(fmt.size() + 128); + + if ((pos = fmt.find("%file")) != string::npos) + fmt.replace(pos, 5, s.file()); + + if ((pos = fmt.find("%text")) != string::npos) + fmt.replace(pos, 5, s.message()); + + if ((pos = fmt.find("%line")) != string::npos) + { + ostringstream ss; + ss << s.line(); + fmt.replace(pos, 5, ss.str()); + } + + _stream << fmt << endl; + } + +} // namespace Test + diff --git a/tests/cppunit/cpptest-assert.h b/tests/cppunit/cpptest-assert.h new file mode 100644 index 000000000..bf90dd842 --- /dev/null +++ b/tests/cppunit/cpptest-assert.h @@ -0,0 +1,424 @@ +// --- +// +// $Id: cpptest-assert.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// Copyright (c) 2010 Nate Gallaher +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_ASSERT_H +#define CPPTEST_ASSERT_H + +#include + +/// Unconditional failure. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param msg Provided message. +/// +/// \par Example: +/// \code +/// void MySuite::test() +/// { +/// // ... +/// +/// switch (flag) +/// { +/// // handling valid cases ... +/// +/// default: +/// TEST_FAIL("This should not happen") +/// } +/// } +/// \endcode +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_FAIL(msg) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, (msg) != 0 ? #msg : "")); \ + if (!continue_after_failure()) return; \ + } + +/// Verify an expression and issues an assertment if it fails. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// +/// \see TEST_ASSERT_MSG(expr, msg) +/// +/// \par Example: +/// \code +/// void MySuite::test() +/// { +/// int i; +/// +/// // ... +/// +/// TEST_ASSERT(i == 13) +/// } +/// \endcode +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_ASSERT(expr) \ + { \ + if (!(expr)) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, #expr)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify an expression and issues an assertment if it fails. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// \param msg User message. +/// +/// \see TEST_ASSERT(expr) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_ASSERT_MSG(expr, msg) \ + { \ + if (!(expr)) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, msg)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify that two expressions are equal, issues an +/// assertment if it fails. Requires the output operator (<<) +/// to be defined for both expected and got. +/// +/// If the output operator is not available, you should use +/// TEST_ASSERT_EQUALS_OBJ(expected, got). +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expected Expected value. +/// \param got Value to test against expected value. +/// +/// \see TEST_ASSERT_EQUALS_MSG(expected, got, msg) +/// \see TEST_ASSERT_EQUALS_OBJ(expected, got) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_ASSERT_EQUALS(expected, got) \ + { \ + if (!((got) == (expected))) \ + { \ + std::stringstream tmpstream; \ + tmpstream << "Got " << (got) << ", expected " << (expected);\ + assertment(::Test::Source(__FILE__, __LINE__, \ + tmpstream.str().c_str())); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify that two expressions are equal, issues an +/// assertment if it fails. +/// +/// If the output operator is defined for the objects being compared +/// you should use TEST_ASSERT_EQUALS(expected, got) instead for +/// more useful failure messages. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expected Expected value. +/// \param got Value to test against expected value. +/// +/// \see TEST_ASSERT_EQUALS(expected, got) +/// \see TEST_ASSERT_EQUALS_MSG(expected, got, msg) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_ASSERT_EQUALS_OBJ(expected, got) \ + { \ + if (!((got) == (expected))) \ + { \ + std::stringstream tmpstream; \ + tmpstream << #expected << " object not equal to "; \ + tmpstream << #got << " object."; \ + assertment(::Test::Source(__FILE__, __LINE__, \ + tmpstream.str().c_str())); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify that two expressions are equal, issues an +/// assertment if it fails. The output operator (<<) must be defined for the +/// object under test. If the output operator is not available, you +/// should use TEST_ASSERT_EQUALS_OBJ(expected, got) instead. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expected Expected value. +/// \param got Value to test against expected value. +/// \param msg User message to print out on failure. +/// +/// \see TEST_ASSERT_EQUALS(expected, got) +/// \see TEST_ASSERT_EQUALS_OBJ(expected, got) +/// +/// For a description of all asserts, see \ref asserts. +#define TEST_ASSERT_EQUALS_MSG(expected, got, msg) \ + { \ + if (!((got) == (expected))) \ + { \ + std::stringstream tmpstream; \ + tmpstream << (msg) << ": "; \ + tmpstream << "Got " << (got) << ", expected " << (expected);\ + assertment(::Test::Source(__FILE__, __LINE__, \ + tmpstream.str().c_str())); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify that two expressions are equal up to a constant, issues an +/// assertment if it fails. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param a First expression to test. +/// \param b Second expression to test. +/// \param delta Constant. +/// +/// \see TEST_ASSERT_DELTA_MSG(a, b, delta, msg) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_ASSERT_DELTA(a, b, delta) \ + { \ + if (((b) < (a) - (delta)) || ((b) > (a) + (delta))) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, \ + "delta(" #a ", " #b ", " #delta ")" )); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify that two expressions are equal up to a constant, issues an +/// assertment if it fails. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param a First expression to test. +/// \param b Second expression to test. +/// \param delta Constant. +/// \param msg User message. +/// +/// \see TEST_ASSERT_DELTA(a, b, delta) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_ASSERT_DELTA_MSG(a, b, delta, msg) \ + { \ + if (((b) < (a) - (delta)) || ((b) > (a) + (delta))) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, msg)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify an expression and expects an exception in return. +/// An assertment is issued if the exception is not thrown. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// \param x Expected exception. +/// +/// \see TEST_THROWS_MSG(expr, x, msg) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_THROWS(expr, x) \ + { \ + bool __expected = false; \ + try { expr; } \ + catch (x) { __expected = true; } \ + catch (...) {} \ + if (!__expected) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, #expr)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify an expression and expects an exception in return. +/// An assertment is issued if the exception is not thrown. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// \param x Expected exception. +/// \param msg User message. +/// +/// \see TEST_THROWS(expr, x) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_THROWS_MSG(expr, x, msg) \ + { \ + bool __expected = false; \ + try { expr; } \ + catch (x) { __expected = true; } \ + catch (...) {} \ + if (!__expected) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, msg)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify an expression and expects any exception in return. +/// An assertment is issued if no exception is thrown. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// +/// \see TEST_THROWS_ANYTHING_MSG(expr, msg) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_THROWS_ANYTHING(expr) \ + { \ + bool __expected = false; \ + try { expr; } \ + catch (...) { __expected = true; } \ + if (!__expected) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, #expr)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify an expression and expects any exception in return. +/// An assertment is issued if no exception is thrown. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// \param msg User message. +/// +/// \see TEST_THROWS_ANYTHING(expr) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_THROWS_ANYTHING_MSG(expr, msg) \ + { \ + bool __expected = false; \ + try { expr; } \ + catch (...) { __expected = true; } \ + if (!__expected) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, msg)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify an expression and expects no exception in return. +/// An assertment is issued if any exception is thrown. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// +/// \see TEST_THROWS_NOTHING_MSG(expr, msg) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_THROWS_NOTHING(expr) \ + { \ + bool __expected = true; \ + try { expr; } \ + catch (...) { __expected = false; } \ + if (!__expected) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, #expr)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// Verify an expression and expects no exception in return. +/// An assertment is issued if any exception is thrown. +/// +/// Used in conjunction with Test::Suite. +/// +/// \param expr Expression to test. +/// \param msg User message. +/// +/// \see TEST_THROWS_NOTHING(expr) +/// +/// For a description of all asserts, see \ref asserts. +/// +#define TEST_THROWS_NOTHING_MSG(expr, msg) \ + { \ + bool __expected = true; \ + try { expr; } \ + catch (...) { __expected = false; } \ + if (!__expected) \ + { \ + assertment(::Test::Source(__FILE__, __LINE__, msg)); \ + if (!continue_after_failure()) return; \ + } \ + } + +/// \page asserts Available asserts +/// +/// Normally, assert macros issues an assert if the given expression, if any, +/// fails (as defined by the macro). Assertments include information about the +/// current test suite, test function, source file, source file line, and a +/// message. The message is normally the offending expression, however, for +/// macros ending in _MSG it is possibly to supply a user defined message. +/// +/// General asserts +/// - TEST_FAIL(msg) +/// +/// Comparision asserts +/// - TEST_ASSERT(expr) +/// - TEST_ASSERT_MSG(expr, msg) +/// - TEST_ASSERT_EQUALS(expected, got) +/// - TEST_ASSERT_EQUALS_MSG(expected, got, msg) +/// - TEST_ASSERT_EQUALS_OBJ(expected, got) +/// - TEST_ASSERT_DELTA(a, b, delta) +/// - TEST_ASSERT_DELTA_MSG(a, b, delta, msg) +/// +/// Exception asserts +/// - TEST_THROWS(expr, x) +/// - TEST_THROWS_MSG(expr, x, msg) +/// - TEST_THROWS_ANYTHING(expr) +/// - TEST_THROWS_ANYTHING_MSG(expr, msg) +/// - TEST_THROWS_NOTHING(expr) +/// - TEST_THROWS_NOTHING_MSG(expr, msg) +/// + +#endif // #ifndef CPPTEST_ASSERT_H + diff --git a/tests/cppunit/cpptest-collectoroutput.h b/tests/cppunit/cpptest-collectoroutput.h new file mode 100644 index 000000000..cd9b65e95 --- /dev/null +++ b/tests/cppunit/cpptest-collectoroutput.h @@ -0,0 +1,106 @@ +// --- +// +// $Id: cpptest-collectoroutput.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_COLLECTOROUTPUT_H +#define CPPTEST_COLLECTOROUTPUT_H + +#include +#include +#include + +#include "cpptest-output.h" +#include "cpptest-source.h" +#include "cpptest-time.h" + +namespace Test +{ + /// \brief Collector output. + /// + /// Base class for output handlers that need to report status when all + /// tests have executed. + /// + class CollectorOutput : public Output + { + public: + virtual void finished(int tests, const Time& time); + virtual void suite_start(int tests, const std::string& name); + virtual void suite_end(int tests, const std::string& name, + const Time& time); + virtual void test_start(const std::string& name); + virtual void test_end(const std::string& name, bool ok, + const Time& time); + virtual void assertment(const Source& s); + + protected: + struct OutputSuiteInfo; + struct OutputTestInfo; + struct OutputErrorTestInfo; + + typedef std::list Sources; + + struct TestInfo + { + std::string _name; + Time _time; + + bool _success : 1; + Sources _sources; + + explicit TestInfo(const std::string name); + }; + + typedef std::vector Tests; + + struct SuiteInfo + { + std::string _name; + int _errors; + Tests _tests; + Time _time; + + SuiteInfo(const std::string& name, int tests); + }; + + typedef std::list Suites; + + Suites _suites; + int _total_errors; + int _total_tests; + Time _total_time; + + CollectorOutput(); + + private: + SuiteInfo* _cur_suite; + TestInfo* _cur_test; + }; + +} // namespace Test + +#endif // #ifndef CPPTEST_COLLECTOROUTPUT_H + diff --git a/tests/cppunit/cpptest-compileroutput.h b/tests/cppunit/cpptest-compileroutput.h new file mode 100644 index 000000000..35a6feb28 --- /dev/null +++ b/tests/cppunit/cpptest-compileroutput.h @@ -0,0 +1,112 @@ +// --- +// +// $Id: cpptest-compileroutput.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_COMPILEROUTPUT_H +#define CPPTEST_COMPILEROUTPUT_H + +#include +#include + +#include "cpptest-output.h" + +namespace Test +{ + /// \brief Compiler-like output handler. + /// + /// %Test suite output handler that only outputs failures in compiler + /// warning/error format. This way, you can use your IDE to browse between + /// failures. + /// + /// The output format is configurable to be able to emulate different + /// compiler outputs. The following modifiers exist: + /// - \e %file Outputs the file containing the test function. + /// - \e %line Line number for the the test function. + /// - \e %text Expression (or message) that caused the assertment. + /// Note that each modifier can only be specified once. + /// + class CompilerOutput : public Output + { + public: + /// \brief Compiler output exception. + /// + /// Indicates that an invalid message format was given when creating + /// a compiler output. The failing format may be retrieved using the + /// what() method. + /// + class InvalidFormat : public std::logic_error + { + public: + InvalidFormat(const std::string& what) + : std::logic_error(what) {} + }; + + /// Pre-defined compiler output formats. + /// + enum Format + { + /// Generic compiler format, which equals: + /// %%file:%%line: %%text + /// + Generic, + + /// + /// Borland C++ Compiler (BCC) format, which equals: + /// Error cpptest %%file %%line: %%text. + /// + BCC, + + /// GNU Compiler Collection + /// (GCC) format, which equals: + /// %%file:%%line: %%text + /// + GCC, + + /// Microsoft Visual C++ + /// (MSVC) format, which equals: + /// %%file(%%line) : %%text + /// + MSVC + }; + + explicit CompilerOutput(Format format = Generic, + std::ostream& stream = std::cout); + + explicit CompilerOutput(const std::string& format, + std::ostream& stream = std::cout); + + virtual void assertment(const Source& s); + + private: + std::string _format; + std::ostream& _stream; + }; + +} // namespace Test + +#endif // #ifndef CPPTEST_COMPILEROUTPUT_H + diff --git a/tests/cppunit/cpptest-htmloutput.h b/tests/cppunit/cpptest-htmloutput.h new file mode 100644 index 000000000..464683f47 --- /dev/null +++ b/tests/cppunit/cpptest-htmloutput.h @@ -0,0 +1,64 @@ +// --- +// +// $Id: cpptest-htmloutput.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_HTMLOUTPUT_H +#define CPPTEST_HTMLOUTPUT_H + +#include +#include + +#include "cpptest-collectoroutput.h" + +namespace Test +{ + /// \brief HTML output. + /// + /// %Output handler that creates a HTML table with detailed information + /// about all tests. + /// + class HtmlOutput : public CollectorOutput + { + public: + void generate(std::ostream& os, bool incl_ok_tests = true, + const std::string& name = ""); + + private: + struct SuiteRow; + struct TestRow; + struct TestSuiteRow; + struct TestResult; + struct TestResultAll; + struct SuiteTestResult; + + friend struct TestSuiteRow; + }; + +} // namespace Test + +#endif // #ifndef CPPTEST_HTMLOUTPUT_H + diff --git a/tests/cppunit/cpptest-output.h b/tests/cppunit/cpptest-output.h new file mode 100644 index 000000000..cfadaecb1 --- /dev/null +++ b/tests/cppunit/cpptest-output.h @@ -0,0 +1,152 @@ +// --- +// +// $Id: cpptest-output.h,v 1.7 2008/07/15 21:20:26 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_OUTPUT_H +#define CPPTEST_OUTPUT_H + +#include + +#ifdef _MSC_VER +# define CPPTEST_UNUSED(x) +#else +# define CPPTEST_UNUSED(x) (void)x +#endif + +namespace Test +{ + class Source; + class Time; + + /// \brief %Test suite output handler. + /// + /// Abstract base class for all suite output handlers. Derive from this + /// class to create real output handlers that creates arbitrary complex + /// output handlers. + /// + /// All parts of testing is reported (test start/stop, suite start/stop, + /// individual test start/stop, and assertments), thus giving maximum + /// flexibility for derived classes. + /// + class Output + { + public: + /// Empty destructor. + /// + virtual ~Output() {} + + /// Called when testing is started. + /// + /// \param tests Total number of tests in all suites. + /// + virtual void initialize(int tests) + { + CPPTEST_UNUSED(tests); + } + + /// Called when testing is finished. + /// + /// \param tests Total number of tests in all suites. + /// \param time Total elapsed time for all tests. + /// + virtual void finished(int tests, const Time& time) + { + CPPTEST_UNUSED(tests); + CPPTEST_UNUSED(time); + } + + /// Called when a suite is entered. + /// + /// \param tests Number of tests in this suite. + /// \param name Name of the suite. + /// + virtual void suite_start(int tests, const std::string& name) + { + CPPTEST_UNUSED(tests); + CPPTEST_UNUSED(name); + } + + /// Called when a suite is finished. + /// + /// \param tests Number of tests in this suite. + /// \param name Name of the suite. + /// \param time Total elapsed time for all tests in this suite. + /// + virtual void suite_end(int tests, const std::string& name, + const Time& time) + { + CPPTEST_UNUSED(tests); + CPPTEST_UNUSED(name); + CPPTEST_UNUSED(time); + } + + /// Called when a tests is executed. + /// + /// \param name Name of the test function. + /// + virtual void test_start(const std::string& name) + { + CPPTEST_UNUSED(name); + } + + /// Called when a test if finished, regardless if an assertment was + /// issued. + /// + /// \param name Name of the test function. + /// \param ok True if the test was successful; false otherwise. + /// \param time Execution time. + /// + virtual void test_end(const std::string& name, bool ok, + const Time& time) + { + CPPTEST_UNUSED(name); + CPPTEST_UNUSED(ok); + CPPTEST_UNUSED(time); + } + + /// Called when an assertment is issued. + /// + /// \param s Assert point information. + /// + virtual void assertment(const Source& s) + { + CPPTEST_UNUSED(s); + } + + protected: + /// Empty constructor. + /// + Output() {} + + private: + Output(const Output&); + Output& operator=(const Output&); + }; + +} // namespace Test + +#endif // #ifndef CPPTEST_OUTPUT_H diff --git a/tests/cppunit/cpptest-source.h b/tests/cppunit/cpptest-source.h new file mode 100644 index 000000000..47140ca71 --- /dev/null +++ b/tests/cppunit/cpptest-source.h @@ -0,0 +1,67 @@ +// --- +// +// $Id: cpptest-source.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_SOURCE_H +#define CPPTEST_SOURCE_H + +#include + +namespace Test +{ + class Suite; + + /// \brief Assertment source information. + /// + /// Contains information about an assertment point. + /// + class Source + { + friend class Suite; + + public: + Source(); + Source(const char* file, unsigned int line, const char* msg); + + const std::string& file() const; + unsigned int line() const; + const std::string& message() const; + const std::string& suite() const; + const std::string& test() const; + + private: + unsigned int _line; + std::string _file; + std::string _msg; + std::string _suite; + std::string _test; + }; + +} // namespace Test + +#endif // #ifndef CPPTEST_SOURCE_H + diff --git a/tests/cppunit/cpptest-suite.h b/tests/cppunit/cpptest-suite.h new file mode 100644 index 000000000..6e9aefc0a --- /dev/null +++ b/tests/cppunit/cpptest-suite.h @@ -0,0 +1,140 @@ +// --- +// +// $Id: cpptest-suite.h,v 1.4 2010/03/26 04:45:14 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_SUITE_H +#define CPPTEST_SUITE_H + +#include +#include +#include + +#include "cpptest-time.h" +#include "cpptest-source.h" + +namespace Test +{ + class Output; + + /// \brief Unit testing suite. + /// + /// Base class for all suites. Derive from this class to create own + /// test suites. + /// + /// %Test functions in derived classes are registered as tests using the + /// TEST_ADD(func). Testing is started by run(). Note that suites may be + /// embedded in other suites using add(). + /// + class Suite + { + public: + Suite(); + virtual ~Suite(); + + void add(std::auto_ptr suite); + + bool run(Output& output, bool cont_after_fail = true); + + protected: + /// Pointer to a test function. + /// + typedef void (Suite::*Func)(); + + bool continue_after_failure() const { return _continue; } + + virtual void setup() {} + virtual void tear_down() {} + + void register_test(Func func, const std::string& name); + void assertment(Source s); + + private: + struct DoRun; + struct ExecTests; + struct SubSuiteTests; + struct SuiteTime; + struct SubSuiteTime; + + friend struct DoRun; + friend struct ExecTests; + friend struct SubSuiteTests; + friend struct SubSuiteTime; + + struct Data + { + Func _func; + std::string _name; + Time _time; + + Data(Func func, const std::string& name) + : _func(func), _name(name) {} + }; + + typedef std::list Tests; + typedef std::list Suites; + + std::string _name; // Suite name + const std::string* _cur_test; // Current test func name + Suites _suites; // External test suites + Tests _tests; // All tests + Output* _output; // Output handler + bool _result : 1; // Test result + bool _success : 1; // Set if no test failed + bool _continue : 1; // Continue func after failures + + void do_run(Output* os, bool cont_after_fail); + int total_tests() const; + Time total_time(bool recursive) const; + + // Disable + // + Suite(const Suite&); + Suite& operator=(const Suite&); + }; + + /// Adds a test function to the enclosing suite. Note that test functions + /// should be added in the suites constructor. + /// + /// \param func Function to add, must be of type Suite::Func. + /// + /// \par Example: + /// \code + /// MySuite::MySuite() + /// { + /// TEST_ADD(&MySuite::test_1) + /// TEST_ADD(&MySuite::test_2) + /// ... + /// } + /// \endcode + /// + #define TEST_ADD(func)\ + register_test(static_cast(&func), #func); + +} // namespace Test + +#endif // #ifndef CPPTEST_SUITE_H + diff --git a/tests/cppunit/cpptest-textoutput.h b/tests/cppunit/cpptest-textoutput.h new file mode 100644 index 000000000..45ed9f2fc --- /dev/null +++ b/tests/cppunit/cpptest-textoutput.h @@ -0,0 +1,88 @@ +// --- +// +// $Id: cpptest-textoutput.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_TEXTOUTPUT_H +#define CPPTEST_TEXTOUTPUT_H + +#include +#include + +#include "cpptest-source.h" +#include "cpptest-output.h" + +namespace Test +{ + /// \brief Text output handler that outputs to the a stream. + /// + /// %Test suite output handler that writes its information as text to a + /// a stream. It it possible to select between two different operational + /// modes that controls the detail level, see Mode. + /// + class TextOutput : public Output + { + public: + /// Output mode. + /// + enum Mode + { + /// Terse output mode, which only shows the number of correct tests. + /// + Terse, + + /// Verbose output mode, which also shows extended assert + /// information for each test that failed. + /// + Verbose + }; + + TextOutput(Mode mode, std::ostream& stream = std::cout); + + virtual void finished(int tests, const Time& time); + virtual void suite_start(int tests, const std::string& name); + virtual void suite_end(int tests, const std::string& name, + const Time& time); + virtual void test_end(const std::string& name, bool ok, + const Time& time); + virtual void assertment(const Source& s); + + private: + typedef std::list ErrorList; + + Mode _mode; + std::ostream& _stream; + ErrorList _suite_error_list; + std::string _suite_name; + int _suite_errors; + int _suite_tests; + int _suite_total_tests; + int _total_errors; + }; + +} // namespace Test + +#endif // #ifndef CPPTEST_TEXTOUTPUT_H diff --git a/tests/cppunit/cpptest-time.h b/tests/cppunit/cpptest-time.h new file mode 100644 index 000000000..ee1f282c9 --- /dev/null +++ b/tests/cppunit/cpptest-time.h @@ -0,0 +1,66 @@ +// --- +// +// $Id: cpptest-time.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_TIME_H +#define CPPTEST_TIME_H + +#include +#include + +namespace Test +{ + /// \brief %Time representation. + /// + /// Encapsulates a time value with microsecond resolution. It is possible + /// to retrieve the current time, add and subtract time values, and output + /// the time to an output stream. + /// + class Time + { + public: + Time(); + Time(unsigned int sec, unsigned int usec); + + unsigned int seconds() const; + unsigned int microseconds() const; + + static Time current(); + + friend Time operator+(const Time& t1, const Time& t2); + friend Time operator-(const Time& t1, const Time& t2); + + friend std::ostream& operator<<(std::ostream& os, const Time& t); + + private: + unsigned int _sec; + unsigned int _usec; + }; + +} // namespace Test + +#endif // #ifndef CPPTEST_TIME_H diff --git a/tests/cppunit/cpptest.h b/tests/cppunit/cpptest.h new file mode 100644 index 000000000..351569471 --- /dev/null +++ b/tests/cppunit/cpptest.h @@ -0,0 +1,42 @@ +// --- +// +// $Id: cpptest.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +/** \file */ + +#ifndef CPPTEST_H +#define CPPTEST_H + +#include "cpptest-assert.h" +#include "cpptest-source.h" +#include "cpptest-suite.h" +#include "cpptest-time.h" + +#include "cpptest-compileroutput.h" +#include "cpptest-htmloutput.h" +#include "cpptest-textoutput.h" + +#endif // #ifndef CPPTEST_H + diff --git a/tests/cppunit/htmloutput.cpp b/tests/cppunit/htmloutput.cpp new file mode 100644 index 000000000..bdf6fd6a4 --- /dev/null +++ b/tests/cppunit/htmloutput.cpp @@ -0,0 +1,453 @@ +// --- +// +// $Id: htmloutput.cpp,v 1.7 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#include +#include + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +#include "cpptest-htmloutput.h" +#include "utils.h" + +using namespace std; + +namespace Test +{ + namespace + { + void + strreplace(string &value, char search, const string &replace) + { + string::size_type idx = 0; + while((idx = value.find(search, idx)) != string::npos) + { + value.replace(idx, 1, replace); + idx += replace.size(); + } + } + + string + escape(string value) + { + strreplace(value, '&', "&"); + strreplace(value, '<', "<"); + strreplace(value, '>', ">"); + strreplace(value, '"', """); + strreplace(value, '\'', "'"); + return value; + } + + void + header(ostream& os, string name) + { + if (!name.empty()) + name += " "; + name = escape(name); + os << + "\n" + "\n" + "\n" + " \n" + " \n" + " \n" + " " << name << "Unit Tests Results\n" + " \n" + " \n" + "\n" + "\n" + "\n" + "\n" + "

" << name << "Unit Tests Results

\n" + "\n" + "
\n" + "Designed by CppTest\n" + "
\n" + "
\n" + "\n"; + } + + void + footer(ostream& os) + { + os << + "\n" + "

\n" + " \n" + " Valid XHTML 1.0 Strict\n" + " \n" + "

\n" + "\n\n"; + } + + void + back_ref(ostream& os, const string& ref, bool prepend_newline = true) + { + + os << "

Back to " << escape(ref) << "\n

\n"; + } + + void + sub_title(ostream& os, const string& title, int size) + { + ostringstream h; + h << "h" << size; + os << "<" << h.str() << ">" << escape(title) << "\n"; + } + + void + sub_title(ostream& os, const string& title, int size, const string& mark) + { + ostringstream h; + h << "h" << size; + os << "<" << h.str() << ">" << escape(title) << "\n"; + } + + enum ClassTableType { TableClass_Summary, TableClass_Suites, TableClass_Suite, TableClass_Result }; + + void + table_header(ostream& os, ClassTableType type, const string &summary = "") + { + static const char* class_tabletypes[] = { "summary", "suites", "suite", "result" }; + + os << "\n"; + } + + void + table_footer(ostream& os) + { + os << "
\n"; + } + + void + table_tr_header(ostream& os) + { + os << " \n"; + } + + void + table_tr_footer(ostream& os) + { + os << " \n"; + } + + enum ClassType { Title, Success, Error }; + + void + table_entry(ostream& os, ClassType type, const string& s, + int width = 0, const string& link = "") + { + static const char* class_types[] = { "title", "success", "error" }; + + os << " " << escape(s) << ""; + else + os << " class=\"tablecell_" << class_types[type] << "\">" << escape(s); + os << "\n"; + } + + } // anonymous namespace + + // Test suite table + // + struct HtmlOutput::SuiteRow + { + ostream& _os; + SuiteRow(ostream& os) : _os(os) {} + void operator()(const SuiteInfo& si) + { + ClassType type(si._errors > 0 ? Error : Success); + ostringstream ss; + + table_tr_header(_os); + table_entry(_os, type, si._name, 0, si._name); + ss.str(""), ss << si._tests.size(); + table_entry(_os, type, ss.str(), 10); + ss.str(""), ss << si._errors; + table_entry(_os, type, ss.str(), 10); + ss.str(""), ss << correct(si._tests.size(), si._errors) << "%"; + table_entry(_os, type, ss.str(), 10); + ss.str(""), ss << si._time; + table_entry(_os, type, ss.str(), 10); + table_tr_footer(_os); + } + }; + + // Individual tests tables, tests + // + struct HtmlOutput::TestRow + { + bool _incl_ok_tests; + ostream& _os; + TestRow(ostream& os, bool incl_ok_tests) + : _incl_ok_tests(incl_ok_tests), _os(os) {} + void operator()(const TestInfo& ti) + { + if (!ti._success || _incl_ok_tests) + { + string link = ti._success ? string(""): + ti._sources.front().suite() + "_" + ti._name; + ClassType type(ti._success ? Success : Error); + ostringstream ss; + + table_tr_header(_os); + table_entry(_os, type, ti._name, 0, link); + ss.str(""), ss << ti._sources.size(); + table_entry(_os, type, ss.str()); + table_entry(_os, type, ti._success ? "true" : "false"); + ss.str(""), ss << ti._time; + table_entry(_os, type, ss.str()); + table_tr_footer(_os); + } + } + }; + + // Individual tests tables, header + // + struct HtmlOutput::TestSuiteRow + { + bool _incl_ok_tests; + ostream& _os; + TestSuiteRow(ostream& os, bool incl_ok_tests) + : _incl_ok_tests(incl_ok_tests), _os(os) {} + void operator()(const SuiteInfo& si) + { + ostringstream ss; + + sub_title(_os, "Suite: " + si._name, 3, si._name); + table_header(_os, TableClass_Suite, "Details for suite " + si._name); + table_tr_header(_os); + table_entry(_os, Title, "Name"); + table_entry(_os, Title, "Errors", 10); + table_entry(_os, Title, "Success", 10); + table_entry(_os, Title, "Time (s)", 10); + table_tr_footer(_os); + for_each(si._tests.begin(), si._tests.end(), + TestRow(_os, _incl_ok_tests)); + table_footer(_os); + back_ref(_os, "top"); + } + }; + + // Individual tests result tables + // + struct HtmlOutput::TestResult + { + ostream& _os; + TestResult(ostream& os) : _os(os) {} + void operator()(const Source& s) + { + const int TitleSize = 15; + + ostringstream ss; + + table_header(_os, TableClass_Result, "Test Failure"); + table_tr_header(_os); + table_entry(_os, Title, "Test", TitleSize); + table_entry(_os, Success, s.suite() + "::" + s.test()); + table_tr_footer(_os); + table_tr_header(_os); + table_entry(_os, Title, "File", TitleSize); + ss << s.file() << ":" << s.line(); + table_entry(_os, Success, ss.str()); + table_tr_footer(_os); + table_tr_header(_os); + table_entry(_os, Title, "Message", TitleSize); + table_entry(_os, Success, s.message()); + table_tr_footer(_os); + table_footer(_os); + } + }; + + // All tests result tables + // + struct HtmlOutput::TestResultAll + { + ostream& _os; + TestResultAll(ostream& os) : _os(os) {} + void operator()(const TestInfo& ti) + { + if (!ti._success) + { + const string& suite = ti._sources.front().suite(); + + sub_title(_os, suite + "::" + ti._name, 3, suite + "_" + ti._name); + for_each(ti._sources.begin(), ti._sources.end(), TestResult(_os)); + back_ref(_os, suite, false); + } + } + }; + + // Individual tests result tables, iterator + // + struct HtmlOutput::SuiteTestResult + { + ostream& _os; + SuiteTestResult(ostream& os) : _os(os) {} + void operator()(const SuiteInfo& si) + { + for_each(si._tests.begin(), si._tests.end(), TestResultAll(_os)); + } + }; + + /// Generates the HTML table. This function should only be called after + /// run(), when all tests have been executed. + /// + /// \param os Output stream. + /// \param incl_ok_tests Set if successful tests should be shown; + /// false otherwise. + /// \param name Name of generated report. + /// + void + HtmlOutput::generate(ostream& os, bool incl_ok_tests, const string& name) + { + ClassType type(_total_errors > 0 ? Error : Success); + ostringstream ss; + + header(os, name); + + // Table: Summary + // + sub_title(os, "Summary", 2); + table_header(os, TableClass_Summary, "Summary of test results"); + table_tr_header(os); + table_entry(os, Title, "Tests", 30); + table_entry(os, Title, "Errors", 30); + table_entry(os, Title, "Success", 30); + table_entry(os, Title, "Time (s)", 10); + table_tr_footer(os); + table_tr_header(os); + ss.str(""), ss << _total_tests; + table_entry(os, type, ss.str(), 30); + ss.str(""), ss << _total_errors; + table_entry(os, type, ss.str(), 30); + ss.str(""), ss << correct(_total_tests, _total_errors) << "%"; + table_entry(os, type, ss.str(), 30); + ss.str(""), ss << _total_time; + table_entry(os, type, ss.str(), 10); + table_tr_footer(os); + table_footer(os); + os << "
\n\n"; + + // Table: Test suites + // + sub_title(os, "Test suites", 2); + table_header(os, TableClass_Suites, "Test Suites"); + table_tr_header(os); + table_entry(os, Title, "Name"); + table_entry(os, Title, "Tests", 10); + table_entry(os, Title, "Errors", 10); + table_entry(os, Title, "Success", 10); + table_entry(os, Title, "Time (s)", 10); + table_tr_footer(os); + for_each(_suites.begin(), _suites.end(), SuiteRow(os)); + table_footer(os); + os << "
\n\n"; + + // Individual tests tables + // + for_each(_suites.begin(), _suites.end(), TestSuiteRow(os, incl_ok_tests)); + os << "
\n\n"; + + // Individual tests result tables + // + if(_total_errors != 0) + { + sub_title(os, "Test results", 2); + for_each(_suites.begin(), _suites.end(), SuiteTestResult(os)); + os << "
\n\n"; + } + // EOF + // + footer(os); + } + +} // namespace Test + diff --git a/tests/cppunit/missing.cpp b/tests/cppunit/missing.cpp new file mode 100644 index 000000000..046dff7b0 --- /dev/null +++ b/tests/cppunit/missing.cpp @@ -0,0 +1,80 @@ +// --- +// +// $Id: missing.cpp,v 1.4 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +#include "missing.h" + +#ifdef HAVE_GETTICKCOUNT + #include +#endif + +#ifndef __BORLANDC__ + #include +#else + #include +#endif + +#include +#include + +namespace Test +{ +#ifndef HAVE_GETTIMEOFDAY + + int + gettimeofday(timeval* tv, void*) + { + assert(tv); + + #ifdef HAVE_GETTICKCOUNT + long now = GetTickCount(); + tv->tv_sec = now / 1000; + tv->tv_usec = (now % 1000) * 1000; + #else + tv->tv_sec = time(0); + tv->tv_usec = 0; + #endif // #ifdef HAVE_GETTICKCOUNT + + return 0; + } + +#endif // #ifndef HAVE_GETTIMEOFDAY + +#ifndef HAVE_ROUND + double + round(double d) + { + return d > 0.0 ? floor(d + 0.5) : ceil(d - 0.5); + } +#endif + +} // namespace Test + diff --git a/tests/cppunit/missing.h b/tests/cppunit/missing.h new file mode 100644 index 000000000..78af19401 --- /dev/null +++ b/tests/cppunit/missing.h @@ -0,0 +1,56 @@ +// --- +// +// $Id: missing.h,v 1.4 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#ifndef CPPTEST_MISSING_H +#define CPPTEST_MISSING_H + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +namespace Test +{ +#ifndef HAVE_GETTIMEOFDAY + + struct timeval + { + long tv_sec; + long tv_usec; + }; + + extern int gettimeofday(timeval* tv, void*); + +#endif // #ifndef HAVE_GETTIMEOFDAY + +#ifndef HAVE_ROUND + extern double round(double d); +#endif + +} // namespace Test + +#endif // #ifndef CPPTEST_MISSING_H diff --git a/tests/cppunit/source.cpp b/tests/cppunit/source.cpp new file mode 100644 index 000000000..b1cebda53 --- /dev/null +++ b/tests/cppunit/source.cpp @@ -0,0 +1,93 @@ +// --- +// +// $Id: source.cpp,v 1.4 2005/06/08 09:25:09 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#include "cpptest-source.h" + +using namespace std; + +namespace Test +{ + /// Constructs an invalid source object, which filename and message are + /// empty strings and the line equals zero. + /// + Source::Source() + : _line(0) + {} + + /// Constructs a source object. + /// + /// \param file Name of the file containing the failing function. + /// \param line Line where the function starts. + /// \param msg Expression (or message) that caused the failure. + /// + Source::Source(const char* file, unsigned int line, const char* msg) + : _line(line), + _file(file ? file : ""), + _msg(msg ? msg : "") + {} + + /// \return Name of the file containing the failing function. + /// + const string& + Source::file() const + { + return _file; + } + + /// \return Line where the function starts. + /// + unsigned int + Source::line() const + { + return _line; + } + + /// \return Descriptive message. + /// + const string& + Source::message() const + { + return _msg; + } + + /// \return Name of the suite, which the test belongs to. + /// + const string& + Source::suite() const + { + return _suite; + } + + /// \return Name of failing test. + /// + const string& + Source::test() const + { + return _test; + } + +} // namespace Test + diff --git a/tests/cppunit/suite.cpp b/tests/cppunit/suite.cpp new file mode 100644 index 000000000..954b4a2c4 --- /dev/null +++ b/tests/cppunit/suite.cpp @@ -0,0 +1,281 @@ +// --- +// +// $Id: suite.cpp,v 1.7 2010/03/26 04:38:25 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#include +#include +#include +#include +#include + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +#include "cpptest-output.h" +#include "cpptest-source.h" +#include "cpptest-suite.h" + +using namespace std; + +namespace Test +{ + namespace + { + // Destroys all dynamically allocated objects within the given range. + // + template + void + destroy_range(FwdIter first, FwdIter last) + { + while (first != last) + delete *first++; + } + + } // anonymous namespace + + /// Constructs an empty test suite. + /// + Suite::Suite() + : _cur_test(0), + _output(0), + _success(true) + {} + + /// Destroys this suite object. + /// + Suite::~Suite() + { + destroy_range(_suites.begin(), _suites.end()); + } + + /// Starts the testing. All tests in this suite and embedded suites will + /// be executed. + /// + /// \param output Progress report destination. + /// \param cont_after_fail Continue functions despite failures. + /// + /// \return True if no test failed; false otherwise. + /// + bool + Suite::run(Output& output, bool cont_after_fail) + { + int ntests = total_tests(); + output.initialize(ntests); + do_run(&output, cont_after_fail); + output.finished(ntests, total_time(true)); + return _success; + } + + /// \fn void Suite::setup() + /// + /// Setups a test fixture. This function is called before each test, + /// in this suite, is executed. + /// + /// This function should be overloaded by derived classes to provide + /// specialized behavior. + /// + /// \see tear_down() + + /// \fn void Suite::tear_down() + /// + /// Tears down a test fixture. This function is called after each test, + /// in this suite, have been executed. + /// + /// This function should be overloaded by derived classes to provide + /// specialized behavior. + /// + /// \see setup() + + /// Adds a suite to this suite. Tests in added suites will be executed + /// when run() of the top-level suite is called. + /// + /// \param suite %Test suite to add. + /// + void + Suite::add(auto_ptr suite) + { + _suites.push_back(suite.release()); + } + + /// Registers a test function. + /// + /// \b Note: Do not call this function directly, use the TEST_ADD(func) + /// macro instead. + /// + /// \param func Pointer to a test function. + /// \param name Class and function name of the function. The format \b must + /// equal \e class::func. + /// + void + Suite::register_test(Func func, const string& name) + { + string::size_type pos = name.find_first_of(':'); + assert(!name.empty() && name[pos + 1] == ':' && name[pos + 2] != '\0'); + + _name.assign(name, 0, pos); + _tests.push_back(Data(func, name.substr(pos + 2))); + } + + /// Issues an assertment to the output handler. + /// + /// Do not call this function directly, use one of the available assertment + /// macros instead, see \ref asserts. + /// + /// \param s Assert point information. + /// + void + Suite::assertment(Source s) + { + s._suite = _name; + s._test = *_cur_test; + _output->assertment(s); + _result = _success = false; + } + + // Functor to execute tests for the given suite. + // + struct Suite::ExecTests + { + Suite& _suite; + + ExecTests(Suite& s) : _suite(s) {} + + void operator()(Data& data) + { + _suite._cur_test = &data._name; + _suite._result = true; // assume success, assert will set to false + _suite._output->test_start(data._name); + + _suite.setup(); + Time start(Time::current()); + // FIXME Also feedback exception to user + try + { + (_suite.*data._func)(); + } catch (...) { + _suite._result = _suite._success = false; + } + Time end(Time::current()); + _suite.tear_down(); + + data._time = end - start; + _suite._output->test_end(data._name, _suite._result, data._time); + } + }; + + // Functor to execute a suite. + // + struct Suite::DoRun + { + bool _continue; + Output* _output; + + DoRun(Output* output, bool cont) : _continue(cont), _output(output) {} + void operator()(Suite* suite) { suite->do_run(_output, _continue); } + }; + + // Execute all tests in this and added suites. + // + void + Suite::do_run(Output* os, bool cont_after_fail) + { + _continue = cont_after_fail; + _output = os; + + _output->suite_start(_tests.size(), _name); + for_each(_tests.begin(), _tests.end(), ExecTests(*this)); + _output->suite_end(_tests.size(), _name, total_time(false)); + + for_each(_suites.begin(), _suites.end(), DoRun(_output, _continue)); + + // FIXME Find a cleaner way + Suites::const_iterator iter = _suites.begin(); + while (iter != _suites.end()) + { + if (!(*iter)->_success) + { + _success = false; + break; + } + iter++; + } + } + + // Functor to count all tests in a suite. + // + struct Suite::SubSuiteTests + { + int operator()(size_t value, const Suite* s) const + { + return value + s->total_tests(); + } + }; + + // Counts all tests in this and all its embedded suites. + // + int + Suite::total_tests() const + { + return accumulate(_suites.begin(), _suites.end(), + _tests.size(), SubSuiteTests()); + } + + // Functor to accumulate execution time for tests. + // + struct Suite::SuiteTime + { + Time operator()(const Time& time, const Data& data) + { + return time + data._time; + } + }; + + // Functor to accumulate execution time for suites. + // + struct Suite::SubSuiteTime + { + Time operator()(Time time, const Suite* s) const + { + return time + s->total_time(true); + } + }; + + // Counts time accumulated execution time for all tests in this and all + // its embedded suites. + // + Time + Suite::total_time(bool recursive) const + { + Time time = accumulate(_tests.begin(), _tests.end(), + Time(), SuiteTime()); + + return !recursive ? time : accumulate(_suites.begin(), _suites.end(), + time, SubSuiteTime()); + } + +} // namespace Test diff --git a/tests/cppunit/textoutput.cpp b/tests/cppunit/textoutput.cpp new file mode 100644 index 000000000..792a89439 --- /dev/null +++ b/tests/cppunit/textoutput.cpp @@ -0,0 +1,132 @@ +// --- +// +// $Id: textoutput.cpp,v 1.4 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#include + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +#include "cpptest-textoutput.h" +#include "cpptest-time.h" +#include "utils.h" + +using namespace std; + +namespace Test +{ + namespace + { + // Outputs detailed assert source information. Used in verbose mode. + // + struct ShowSource + { + ostream& _stream; + ShowSource(ostream& stream) : _stream(stream) {} + void operator()(const Source& s) + { + _stream << "\tTest: " << s.test() << endl + << "\tSuite: " << s.suite() << endl + << "\tFile: " << s.file() << endl + << "\tLine: " << s.line() << endl + << "\tMessage: " << s.message() << endl << endl; + + } + }; + + } // anonymous namespace + + /// Constructs a text output handler. + /// + /// \param mode Output mode. + /// \param stream Stream to output to. + /// + TextOutput::TextOutput(Mode mode, ostream& stream) + : _mode(mode), + _stream(stream), + _total_errors(0) + {} + + void + TextOutput::finished(int tests, const Time& time) + { + _stream << "Total: " << tests << " tests, " + << correct(tests, _total_errors) << "% correct" + << " in " << time << " seconds" << endl; + } + + void + TextOutput::suite_start(int tests, const string& name) + { + if (tests > 0) + { + _suite_name = name; + _suite_tests = _suite_errors = 0; + _suite_total_tests = tests; + _suite_error_list.clear(); + + _stream << _suite_name << ": " + << "0/" << _suite_total_tests + << "\r" << flush; + } + } + + void + TextOutput::suite_end(int tests, const string& name, const Time& time) + { + if (tests > 0) + { + _stream << name << ": " << tests << "/" << tests << ", " + << correct(tests, _suite_errors) << "% correct" + << " in " << time << " seconds" << endl; + + if (_mode == Verbose && _suite_errors) + for_each(_suite_error_list.begin(), _suite_error_list.end(), + ShowSource(_stream)); + + _total_errors += _suite_errors; + } + } + + void + TextOutput::test_end(const string&, bool ok, const Time&) + { + _stream << _suite_name << ": " + << ++_suite_tests << "/" << _suite_total_tests + << "\r" << flush; + if (!ok) + ++_suite_errors; + } + + void + TextOutput::assertment(const Source& s) + { + _suite_error_list.push_back(s); + } + +} // namespace Test diff --git a/tests/cppunit/time.cpp b/tests/cppunit/time.cpp new file mode 100644 index 000000000..4b7a988f5 --- /dev/null +++ b/tests/cppunit/time.cpp @@ -0,0 +1,176 @@ +// --- +// +// $Id: time.cpp,v 1.4 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +#include "missing.h" +#include "cpptest-time.h" + +#ifdef HAVE_GETTIMEOFDAY + #ifdef HAVE_SYS_TIME_H + #include + #else + #include + #endif +#endif + +using namespace std; + +namespace Test +{ + namespace + { + const unsigned int UsecPerSec = 1000000; + + } // anonymous namespace + + /// Constructs a time object with zeroed time. + /// + Time::Time() + : _sec(0), + _usec(0) + {} + + /// Constructs a time object. + /// + /// \param sec Seconds. + /// \param usec Micro-seconds. + /// + Time::Time(unsigned int sec, unsigned int usec) + : _sec(sec), + _usec(usec) + {} + + /// \return Seconds. + /// + unsigned int + Time::seconds() const + { + return _sec; + } + + /// \return Micro-seconds. + /// + unsigned int + Time::microseconds() const + { + return _usec; + } + + /// \return The current time. + /// + Time + Time::current() + { + struct timeval tv; + gettimeofday(&tv, 0); + return Time(tv.tv_sec, tv.tv_usec); + } + + /// \relates Time + /// + /// Computes the time elapsed between two time values. + /// + /// \param t1 Left-hand time, should be greater than \a t2. + /// \param t2 Right-hand time, should be less than \a t1. + /// + /// \return Computed time value. + /// + Time + operator-(const Time& t1, const Time& t2) + { + if (t2._sec > t1._sec || (t2._sec == t1._sec && t2._usec > t1._usec)) + return Time(); + + unsigned int sec = t1._sec - t2._sec; + unsigned int usec; + + if (t2._usec > t1._usec) + { + --sec; + usec = UsecPerSec - (t2._usec - t1._usec); + } + else + usec = t1._usec - t2._usec; + + return Time(sec, usec); + } + + /// \relates Time + /// + /// Adds two time values. + /// + /// \param t1 Left-hand time. + /// \param t2 Right-hand time. + /// + /// \return Computed time value. + /// + Time + operator+(const Time& t1, const Time& t2) + { + unsigned int sec = t1._sec + t2._sec; + unsigned int usec = t1._usec + t2._usec; + + if (usec > UsecPerSec) + { + ++sec; + usec -= UsecPerSec; + } + return Time(sec, usec); + } + + /// \relates Time + /// + /// Outputs a time to an output stream. + /// + /// \param os Output stream to write to. + /// \param t %Time to output. + /// + /// \return A reference to the given output stream. + /// + ostream& + operator<<(ostream& os, const Time& t) + { + int old_fill(os.fill()); + int old_width(os.width()); + + os << t.seconds() << '.'; + os.fill('0'); + os.width(6); + os << t.microseconds(); + + os.fill(old_fill); + os.width(old_width); + + return os; + } + +} // namespace Test + diff --git a/tests/cppunit/utils.cpp b/tests/cppunit/utils.cpp new file mode 100644 index 000000000..ebf850239 --- /dev/null +++ b/tests/cppunit/utils.cpp @@ -0,0 +1,50 @@ +// --- +// +// $Id: utils.cpp,v 1.5 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + + +#if (defined(__WIN32__) || defined(WIN32)) +# include "winconfig.h" +#else +# include "config.h" +#endif + +#include "missing.h" +#include "utils.h" + +namespace Test +{ + // Computes the procentage of correct tests. + // + int + correct(int tests, int errors) + { + if ((errors == 0) || (tests == 0)) + return 100; + + return (tests - errors) * 100 / tests; + } + +} // namespace Test diff --git a/tests/cppunit/utils.h b/tests/cppunit/utils.h new file mode 100644 index 000000000..967e0afaf --- /dev/null +++ b/tests/cppunit/utils.h @@ -0,0 +1,36 @@ +// --- +// +// $Id: utils.h,v 1.3 2005/06/08 08:08:06 nilu Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#ifndef CPPTEST_UTILS_H +#define CPPTEST_UTILS_H + +namespace Test +{ + extern int correct(int tests, int errors); + +} // namespace Test + +#endif // #ifndef CPPTEST_UTILS_H diff --git a/tests/cppunit/winconfig.h b/tests/cppunit/winconfig.h new file mode 100644 index 000000000..6b2858a62 --- /dev/null +++ b/tests/cppunit/winconfig.h @@ -0,0 +1,44 @@ +// --- +// +// $Id: winconfig.h,v 1.1 2008/07/15 20:33:31 hartwork Exp $ +// +// CppTest - A C++ Unit Testing Framework +// Copyright (c) 2003 Niklas Lundell +// +// --- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. +// +// --- + +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +// Capabilities +// +#define HAVE_GETTICKCOUNT + +// Compiler specific stuff +// +#if _MSC_VER == 1200 // MS Visual C++ 6.0 + #pragma warning (disable: 4786) +#endif + +#if _MSC_VER > 1300 // MS Visual C++ .NET 2002 and above + #pragma warning (disable: 4267) +#endif + +#endif // #ifndef TEST_CONFIG_H diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h new file mode 100644 index 000000000..7cb579c6c --- /dev/null +++ b/tests/fixed_memory_test.h @@ -0,0 +1,150 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_TESTS_FIXED_MEMORY_H +#define __EQEMU_TESTS_FIXED_MEMORY_H + +#include "cppunit/cpptest.h" +#include "../common/fixed_memory_hash_set.h" +#include "../common/Item.h" + +class FixedMemoryHashTest : public Test::Suite { + typedef void(FixedMemoryHashTest::*TestFunction)(void); +public: + FixedMemoryHashTest() { + size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); + data_ = new uint8[size_]; + memset(data_, 0, size_); + TEST_ADD(FixedMemoryHashTest::InitTest); + TEST_ADD(FixedMemoryHashTest::LoadTest); + TEST_ADD(FixedMemoryHashTest::InsertTest); + TEST_ADD(FixedMemoryHashTest::RetrieveTest); + TEST_ADD(FixedMemoryHashTest::OverwriteTest); + TEST_ADD(FixedMemoryHashTest::OverwriteRetrieveTest); + TEST_ADD(FixedMemoryHashTest::InsertAgainTest); + TEST_ADD(FixedMemoryHashTest::RetrieveAgainTest); + } + ~FixedMemoryHashTest() { + delete[] data_; + } + + void InitTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); + TEST_ASSERT(!hash.exists(1001)); + TEST_ASSERT(hash.size() == 0); + TEST_ASSERT(hash.max_size() == 72000); + TEST_ASSERT(hash.empty()); + } + + void LoadTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_); + TEST_ASSERT(!hash.exists(1001)); + TEST_ASSERT(hash.size() == 0); + TEST_ASSERT(hash.max_size() == 72000); + TEST_ASSERT(hash.empty()); + } + + void InsertTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_); + Item_Struct item; + memset(&item, 0, sizeof(item)); + strcpy(item.Name, "Iron Sword"); + item.ID = 1001; + hash.insert(1001, item); + + TEST_ASSERT(hash.exists(1001)); + TEST_ASSERT(hash.size() == 1); + TEST_ASSERT(hash.max_size() == 72000); + TEST_ASSERT(!hash.empty()); + } + + void RetrieveTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_); + TEST_ASSERT(hash.exists(1001)); + TEST_ASSERT(hash.size() == 1); + TEST_ASSERT(hash.max_size() == 72000); + TEST_ASSERT(!hash.empty()); + + Item_Struct item = hash[1001]; + TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); + TEST_ASSERT(item.ID == 1001); + } + + void OverwriteTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_); + Item_Struct item; + memset(&item, 0, sizeof(item)); + strcpy(item.Name, "Steel Sword"); + item.ID = 1001; + hash.insert(1001, item); + + TEST_ASSERT(hash.exists(1001)); + TEST_ASSERT(hash.size() == 1); + TEST_ASSERT(hash.max_size() == 72000); + TEST_ASSERT(!hash.empty()); + } + + void OverwriteRetrieveTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_); + TEST_ASSERT(hash.exists(1001)); + TEST_ASSERT(hash.size() == 1); + TEST_ASSERT((hash.max_size() == 72000)); + TEST_ASSERT(!hash.empty()); + + Item_Struct item = hash[1001]; + TEST_ASSERT(strcmp(item.Name, "Steel Sword") == 0); + TEST_ASSERT(item.ID == 1001); + } + + void InsertAgainTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_); + Item_Struct item; + memset(&item, 0, sizeof(item)); + strcpy(item.Name, "Iron Sword"); + item.ID = 1000; + hash.insert(1000, item); + + TEST_ASSERT(hash.exists(1000)); + TEST_ASSERT(hash.exists(1001)); + TEST_ASSERT(hash.size() == 2); + TEST_ASSERT(hash.max_size() == 72000); + TEST_ASSERT(!hash.empty()); + } + + void RetrieveAgainTest() { + EQEmu::FixedMemoryHashSet hash(data_, size_); + TEST_ASSERT(hash.exists(1000)); + TEST_ASSERT(hash.exists(1001)); + TEST_ASSERT(hash.size() == 2); + TEST_ASSERT(hash.max_size() == 72000); + TEST_ASSERT(!hash.empty()); + + Item_Struct item = hash[1000]; + TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); + TEST_ASSERT(item.ID == 1000); + + item = hash[1001]; + TEST_ASSERT(strcmp(item.Name, "Steel Sword") == 0); + TEST_ASSERT(item.ID == 1001); + } +private: + uint8 *data_; + size_t size_; +}; + +#endif diff --git a/tests/ipc_mutex_test.h b/tests/ipc_mutex_test.h new file mode 100644 index 000000000..f94a342a1 --- /dev/null +++ b/tests/ipc_mutex_test.h @@ -0,0 +1,63 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_TESTS_IPC_MUTEX_H +#define __EQEMU_TESTS_IPC_MUTEX_H + +#include "cppunit/cpptest.h" +#include "../common/ipc_mutex.h" + +class IPCMutexTest : public Test::Suite { + typedef void(IPCMutexTest::*TestFunction)(void); +public: + IPCMutexTest() { + TEST_ADD(IPCMutexTest::LockMutexTest); + TEST_ADD(IPCMutexTest::UnlockMutexTest); + TEST_ADD(IPCMutexTest::DoubleLockMutexTest); + TEST_ADD(IPCMutexTest::DoubleUnlockMutexTest); + } + + ~IPCMutexTest() { + } + + void LockMutexTest() { + EQEmu::IPCMutex mutex("TestMutex1"); + TEST_ASSERT(mutex.Lock()); + TEST_ASSERT(mutex.Unlock()); + } + + void UnlockMutexTest() { + EQEmu::IPCMutex mutex("TestMutex2"); + TEST_ASSERT(!mutex.Unlock()); + } + + void DoubleLockMutexTest() { + EQEmu::IPCMutex mutex("TestMutex3"); + TEST_ASSERT(mutex.Lock()); + TEST_ASSERT(!mutex.Lock()); + } + + void DoubleUnlockMutexTest() { + EQEmu::IPCMutex mutex("TestMutex4"); + TEST_ASSERT(mutex.Lock()); + TEST_ASSERT(mutex.Unlock()); + TEST_ASSERT(!mutex.Unlock()); + } +}; + +#endif diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 000000000..2d09c32e5 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,64 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include "memory_mapped_file_test.h" +#include "ipc_mutex_test.h" +#include "fixed_memory_test.h" + +int main() { + try { + std::unique_ptr output(new Test::HtmlOutput); + Test::Suite tests; + tests.add(std::auto_ptr(new MemoryMappedFileTest())); + tests.add(std::auto_ptr(new IPCMutexTest())); + tests.add(std::auto_ptr(new FixedMemoryHashTest())); + tests.run(*output, true); + + std::ofstream outfile("tests.html"); + Test::HtmlOutput* const html = dynamic_cast(output.get()); + if(html) + html->generate(outfile, true, "EQEmuTests"); + + outfile.close(); + } catch(...) { + getchar(); + return -1; + } + getchar(); + return 0; +} \ No newline at end of file diff --git a/tests/memory_mapped_file_test.h b/tests/memory_mapped_file_test.h new file mode 100644 index 000000000..3ecdb30ff --- /dev/null +++ b/tests/memory_mapped_file_test.h @@ -0,0 +1,66 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_TESTS_MEMORY_MAPPED_FILE_H +#define __EQEMU_TESTS_MEMORY_MAPPED_FILE_H + +#include "cppunit/cpptest.h" +#include "../common/memory_mapped_file.h" + +class MemoryMappedFileTest : public Test::Suite { + typedef void(MemoryMappedFileTest::*TestFunction)(void); +public: + MemoryMappedFileTest() { + TEST_ADD(MemoryMappedFileTest::LoadAndZeroMMF) + TEST_ADD(MemoryMappedFileTest::LoadExistingMMF) + } + + ~MemoryMappedFileTest() { + } + + private: + + void LoadAndZeroMMF() { + EQEmu::MemoryMappedFile mmf("testfile.txt", 512); + mmf.ZeroFile(); + TEST_ASSERT(!mmf.Loaded()); + TEST_ASSERT(mmf.Size() == 512); + + unsigned char *data = reinterpret_cast(mmf.Get()); + TEST_ASSERT(data != NULL); + + *reinterpret_cast(data) = 562; + mmf.SetLoaded(); + + TEST_ASSERT(mmf.Loaded()); + } + + void LoadExistingMMF() { + EQEmu::MemoryMappedFile mmf("testfile.txt"); + TEST_ASSERT(mmf.Size() == 512); + TEST_ASSERT(mmf.Loaded()); + + unsigned char *data = reinterpret_cast(mmf.Get()); + TEST_ASSERT(data != NULL); + + uint32 val = *reinterpret_cast(data); + TEST_ASSERT(val == 562); + } +}; + +#endif