From: hama Date: Sat, 31 May 2014 14:33:52 +0000 (+0200) Subject: test rplexception ready, rplmatrix: 2/3 X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=ba59c8c8e2b1504564f9c9ce6e0220e3434743f9;p=reqt test rplexception ready, rplmatrix: 2/3 --- diff --git a/rplcore/rplcore.hpp b/rplcore/rplcore.hpp index 3753903..f630fd7 100644 --- a/rplcore/rplcore.hpp +++ b/rplcore/rplcore.hpp @@ -27,6 +27,7 @@ #include #include #include +#include typedef unsigned char uint8_t; #include "rplmodules.hpp" diff --git a/rplcore/rplexception.cpp b/rplcore/rplexception.cpp index 358fb0b..fac6605 100644 --- a/rplcore/rplexception.cpp +++ b/rplcore/rplexception.cpp @@ -28,76 +28,20 @@ class RplException; /** * @brief Constructor. * - * @param message the reason of the exception + * For derived classes only! */ -RplException::RplException(const char* message) : - m_message(message) { +RplException::RplException() : + m_message("") +{ } /** * @brief Constructor. * - * @param message the reason of the exception + * @param format the reason of the exception + * @param ... the values for the placeholders in the format. */ -RplException::RplException(const QByteArray& message) : - m_message(message) { -} - -/** - * @brief Constructor. - * - * This constructor automatically logs the given data. - * - * @param level the logging level, e.g. LOG_ERROR - * @param location an unique identifier for the location - * where the exception was thrown - * @param message the reason - * @param logger if NULL the global logger will be used - */ -RplException::RplException(RplLoggerLevel level, int location, - const char* message, RplLogger* logger) : - m_message(message) { - if(logger == NULL) - logger = RplLogger::globalLogger(); - logger->log(level, location, message); -} - -/** - * @brief Constructor. - * - * This constructor automatically logs the given data. - * - * @param level the logging level, e.g. LOG_ERROR - * @param location an unique identifier for the location - * where the exception was thrown - * @param message the reason - * @param logger Nif NULL the global logger will be used - */ -RplException::RplException(RplLoggerLevel level, int location, - const QByteArray& message, RplLogger* logger) : - m_message(message) { - if(logger == NULL) - logger = RplLogger::globalLogger(); - logger->log(level, location, message); -} - -/** - * @brief Constructor. - * - * This constructor automatically logs the given data. - * - * @param level the logging level, e.g. LOG_ERROR - * @param location an unique identifier for the location - * where the exception was thrown - * @param format the reason of the exception. - * Can contain placeholders (@see - * std::printf()) - * @param ... the values of the placeholders - * in format - * @param logger if NULL the global logger will be used - */ -RplException::RplException(RplLoggerLevel level, int location, - RplLogger* logger, const char* format, ...) : +RplException::RplException(const char* format, ...) : m_message("") { char buffer[64000]; va_list ap; @@ -105,9 +49,6 @@ RplException::RplException(RplLoggerLevel level, int location, vsnprintf(buffer, sizeof buffer, format, ap); va_end(ap); m_message = buffer; - if(logger == NULL) - logger = RplLogger::globalLogger(); - logger->log(level, location, buffer); } /** @@ -126,8 +67,7 @@ RplException::RplException(RplLoggerLevel level, int location, * @param logger if NULL the global logger will be used */ RplException::RplException(RplLoggerLevel level, int location, - RplLogger* logger, - const QByteArray& format, ...) : + RplLogger* logger, const char* format, ...) : m_message("") { char buffer[64000]; va_list ap; diff --git a/rplcore/rplexception.hpp b/rplcore/rplexception.hpp index e3c7d02..64fd530 100644 --- a/rplcore/rplexception.hpp +++ b/rplcore/rplexception.hpp @@ -12,18 +12,16 @@ #ifndef RPLCORE_HPP #include #endif + class RplException { +protected: + RplException(); public: - RplException(const char* message); - RplException(const QByteArray& message); + RplException(const char* message, ...); RplException(RplLoggerLevel level, int location, const char* message, RplLogger* logger = NULL); - RplException(RplLoggerLevel level, int location, const QByteArray& message, - RplLogger* logger = NULL); RplException(RplLoggerLevel level, int location, RplLogger* logger, const char* message, ...); - RplException(RplLoggerLevel level, int location, RplLogger* logger, - const QByteArray& message, ...); const QByteArray& getMessage() const { return m_message; } @@ -41,7 +39,7 @@ public: class RplInvalidDataException : public RplException { public: RplInvalidDataException(RplLoggerLevel level, int location, const char* message, - const void* data = NULL, size_t dataSize = 0, RplLogger* logger = NULL); + const void* data = NULL, size_t dataSize = 0, RplLogger* logger = NULL); }; #endif // RPLEXCEPTION_HPP diff --git a/rplcore/rpllogger.cpp b/rplcore/rpllogger.cpp index cb7468e..e044b97 100644 --- a/rplcore/rpllogger.cpp +++ b/rplcore/rpllogger.cpp @@ -439,7 +439,6 @@ void RplLogger::buildStandardAppender(const QByteArray& prefix, int maxSize, RplFileAppender* fileAppender = new RplFileAppender(prefix, maxSize, maxCount); fileAppender->setAutoDelete(true); addAppender((RplAppender*) fileAppender); - } /** @class RplStreamAppender rpllogger.hpp "rplcore/rpllogger.hpp" @@ -584,7 +583,9 @@ void RplFileAppender::log(RplLoggerLevel level, int location, RplMemoryAppender::RplMemoryAppender(int maxLines, const char* appenderName) : RplAppender(appenderName), m_lines(), - m_maxLines(maxLines) { + m_maxLines(maxLines), + m_addPrefix(true) +{ m_lines.reserve(maxLines); } @@ -608,7 +609,13 @@ void RplMemoryAppender::log(RplLoggerLevel level, int location, RplLogger* logger) { if(m_lines.size() >= m_maxLines) m_lines.removeFirst(); - m_lines.append(message); + if (! m_addPrefix) + m_lines.append(message); + else { + QByteArray msg(logger->getStdPrefix(level, location)); + msg += message; + m_lines.append(msg); + } } #pragma GCC diagnostic warning "-Wunused-parameter" diff --git a/rplcore/rpllogger.hpp b/rplcore/rpllogger.hpp index 69c8059..37e56eb 100644 --- a/rplcore/rpllogger.hpp +++ b/rplcore/rpllogger.hpp @@ -161,6 +161,8 @@ private: QVector m_lines; // maximum count of m_lines. If larger the oldest lines will be deleted. int m_maxLines; + // true: standard prefix (level + datetime) will be stored too. + bool m_addPrefix; }; #endif // RPLLOGGER_HPP diff --git a/rplcore/rplstring.cpp b/rplcore/rplstring.cpp index 40e1308..f174564 100644 --- a/rplcore/rplstring.cpp +++ b/rplcore/rplstring.cpp @@ -365,6 +365,5 @@ public: void testRplString() { #ifdef RPL_TEST TestRplString test; - test.run(); #endif } diff --git a/rplcore/rpltest.cpp b/rplcore/rpltest.cpp index cf74fc0..1b9adfd 100644 --- a/rplcore/rpltest.cpp +++ b/rplcore/rpltest.cpp @@ -26,9 +26,14 @@ class RplTest; RplTest::RplTest(const char* name) : m_errors(0), m_name(name), - m_logger() { + m_logger(), + m_memoryAppender(1024), + m_memoryLogger() +{ + m_memoryAppender.setAutoDelete(false); m_logger.buildStandardAppender(getTempDir("rpltest")); log(QByteArray("Start of ") + m_name); + m_memoryLogger.addAppender(&m_memoryAppender); } /** @@ -38,7 +43,9 @@ void RplTest::run() { try { doIt(); } catch(RplException e) { - error("unexpected RplException: %s", e.getMessage().data()); + error("unexpected RplException: %s", e.getMessage().constData()); + } catch(...){ + error("unknown Exception"); } if(m_errors > 0) { @@ -297,6 +304,30 @@ bool RplTest::error(const char* format, ...) { return false; } +/** + * @brief Tests whether the m_memoryLogger has a message containing a given pattern. + * + * @param pattern regular expression to search + * @return true: pattern has been found
+ * false: otherwise + */ +bool RplTest::logContains(const char* pattern) +{ + const QVector& lines = m_memoryAppender.getLines(); + QRegularExpression rexpr(pattern); + bool rc = false; + QRegularExpressionMatch match; + for (int ii = 0; ii < lines.size(); ii++){ + const QByteArray& line = lines.at(ii); + match = rexpr.match(line); + if (match.hasMatch()){ + rc = true; + break; + } + } + return rc; +} + /** * @brief Returns the name of a directory in the temp dir. * diff --git a/rplcore/rpltest.hpp b/rplcore/rpltest.hpp index 903f729..536bdbf 100644 --- a/rplcore/rpltest.hpp +++ b/rplcore/rpltest.hpp @@ -43,13 +43,18 @@ public: bool withSeparator = true); QByteArray getTempFile(const char* node, const char* parent = NULL, bool deleteIfExists = true); + bool logContains(const char* pattern); void run(); - virtual void doIt() = 0; +protected: + virtual void doIt(void) = 0; protected: int m_errors; QByteArray m_name; RplLogger m_logger; + // for testing of logging code: + RplMemoryAppender m_memoryAppender; + RplLogger m_memoryLogger; char m_separator; }; #define checkE(expected, current) assertEquals(expected, current, __FILE__, __LINE__) diff --git a/rplmath/rplmatrix.cpp b/rplmath/rplmatrix.cpp index 4bea419..86c2a4f 100644 --- a/rplmath/rplmatrix.cpp +++ b/rplmath/rplmatrix.cpp @@ -7,11 +7,11 @@ #include "rplmath/rplmath.hpp" -RplMatrixException::RplMatrixException(int id, const RplMatrix& RplMatrix, +RplMatrixException::RplMatrixException(const RplMatrix& RplMatrix, const char* format, ...) : - m_message() + RplException() { - if (! RplMatrix.getName().empty()) + if (! RplMatrix.getName().isEmpty()) m_message = RplMatrix.getName() + ": "; char buffer[16*1024]; @@ -21,16 +21,6 @@ RplMatrixException::RplMatrixException(int id, const RplMatrix& RplMatrix, va_end(args); m_message += buffer; } -RplMatrixException::RplMatrixException(const char* format, ...) -{ - char buffer[16*1024]; - - va_list args; - va_start(args, format); - vsnprintf(buffer, sizeof buffer, format, args); - va_end(args); - m_message = buffer; -} /** * Constructor. @@ -71,9 +61,9 @@ RplMatrix::~RplMatrix() { */ RplMatrix::RplMatrix(const RplMatrix& source) : m_rows(0), - m_cols(), + m_cols(0), m_values(NULL), - m_name(source.m_name + std::string("-copy")) + m_name(source.m_name + QByteArray("-copy")) { resize(source.m_rows, source.m_cols, source.m_values); } @@ -121,12 +111,12 @@ void RplMatrix::checkSameDimension(const RplMatrix& operand) const { if (m_rows != operand.getRows()) throw RplMatrixException(*this, - "RplMatrix %s has different row count: %d / %d", - operand.getName().c_str(), m_rows, operand.getRows()); + "%s has a different row count: %d / %d", + operand.getName().constData(), m_rows, operand.getRows()); if (m_cols != operand.getCols()) throw RplMatrixException(*this, - "RplMatrix %s has different column count: %d / %d", - operand.getName().c_str(), m_cols, operand.getCols()); + "%s has a different column count: %d / %d", + operand.getName().constData(), m_cols, operand.getCols()); } /** @@ -288,21 +278,18 @@ RplMatrix& RplMatrix::resize(int rows, int cols, const MatVal values[], if (rows != m_rows || cols != m_cols){ delete m_values; m_values = new MatVal[rows * cols]; + m_rows = rows; + m_cols = cols; } - int ix = -1; if (values == NULL) { - for (int row = 0; row < m_rows; row++){ - for (int col = 0; row < m_cols; col++) - m_values[++ix] = defaultValue; + for (int ix = rows*cols - 1; ix >= 0; ix--){ + m_values[ix] = defaultValue; } } else { - for (int row = 0; row < m_rows; row++){ - for (int col = 0; row < m_cols; col++){ - ix++; - m_values[ix] = values[ix]; - } - } + for (int ix = rows*cols - 1; ix >= 0; ix--){ + m_values[ix] = values[ix]; + } } return *this; } @@ -345,12 +332,12 @@ RplMatrix RplMatrix::transpose() const } return rc; } -std::string RplMatrix::toString(const char* prefix, const char* format, +QByteArray RplMatrix::toString(const char* prefix, const char* format, const char* rowSeparator, const char* colSeparator) const { char buffer[128]; Tuple2 minMaxi(minMax()); - std::string rc; + QByteArray rc; snprintf(buffer, sizeof buffer, format, minMaxi.m_value1); int length = strlen(buffer); snprintf(buffer, sizeof buffer, format, minMaxi.m_value2); diff --git a/rplmath/rplmatrix.hpp b/rplmath/rplmatrix.hpp index a20aa21..9082408 100644 --- a/rplmath/rplmatrix.hpp +++ b/rplmath/rplmatrix.hpp @@ -13,16 +13,10 @@ class RplMatrix; /** * Implements a RplMatrix specific exception. */ -class RplMatrixException +class RplMatrixException : public RplException { public: - explicit RplMatrixException(int id, const char* format, ...); - explicit RplMatrixException(const RplMatrix& RplMatrix, const char* format, ...); -public: - const std::string getMessage() const - { return m_message; } -private: - std::string m_message; + RplMatrixException(const RplMatrix& RplMatrix, const char* format, ...); }; /** @@ -66,7 +60,7 @@ public: inline bool operator !=(MatVal operand) { return ! (*this == operand); } public: - inline const std::string& getName() const + inline const QByteArray& getName() const { return m_name; } inline MatVal get(int row, int col) const { check(row, col); return m_values[row*m_cols + col]; } @@ -84,7 +78,7 @@ public: MatVal defaultValue = 0.0); Tuple2 minMax() const; RplMatrix transpose() const; - std::string toString(const char* prefix = NULL, + QByteArray toString(const char* prefix = NULL, const char* format = "%f", const char* rowSeparator = "\n", const char* colSeparator = ",") const; @@ -96,7 +90,7 @@ protected: int m_rows; int m_cols; MatVal* m_values; - std::string m_name; + QByteArray m_name; }; #endif /* RplMatrix_HPP_ */ diff --git a/unittests/main.cpp b/unittests/main.cpp index 5ebbca5..be1c41c 100644 --- a/unittests/main.cpp +++ b/unittests/main.cpp @@ -12,10 +12,11 @@ int main(int argc, char *argv[]) { - //QCoreApplication a(argc, argv); if (argc > 1) printf("not used: %s\n", argv[1]); - //return a.exec(); extern void testRplMatrix(); testRplMatrix(); + + extern void testRplException(); + testRplException(); } diff --git a/unittests/rplexception_test.cpp b/unittests/rplexception_test.cpp new file mode 100644 index 0000000..b39f308 --- /dev/null +++ b/unittests/rplexception_test.cpp @@ -0,0 +1,48 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ +#include "rplcore/rplcore.hpp" +#include "rplcore/rpltest.hpp" + +class TestRplException : public RplTest{ +public: + TestRplException() : RplTest("RplException") {} + +public: + void testBasic() { + try{ + throw RplException("simple"); + checkF(true); + } catch (RplException exc){ + checkE("simple", exc.getMessage().constData()); + } + try{ + throw RplException("String: %s and int %d", "Hi", -333); + checkF(true); + } catch (RplException exc){ + checkE("String: Hi and int -333", exc.getMessage().constData()); + } + try{ + throw RplException(LOG_INFO, 1234, &m_memoryLogger, + "String: %s and int %d", "Hi", -333); + checkF(true); + } catch (RplException exc){ + checkT(logContains("^ .*\\(1234\\): String: Hi and int -333")); + } + log("ok"); + } + virtual void doIt() { + testBasic(); + } +}; +void testRplException() { + TestRplException test; + test.run(); +} + + + diff --git a/unittests/rplmatrix_test.cpp b/unittests/rplmatrix_test.cpp index 5bd8215..37a1729 100644 --- a/unittests/rplmatrix_test.cpp +++ b/unittests/rplmatrix_test.cpp @@ -13,16 +13,45 @@ public: TestRplMatrix() : RplTest("RplMatrix") {} public: + void fillMatrix(RplMatrix& mx, MatVal offset = 0){ + for(int row = 0; row < mx.getRows(); row++){ + for (int col = 0; col < mx.getCols(); col++){ + mx.set(row, col, 100.0*row + col + offset); + } + } + } + void checkMatrix(const RplMatrix& mx, MatVal offset = 0){ + int count = 0; + for(int row = 0; row < mx.getRows(); row++){ + for (int col = 0; col < mx.getCols(); col++){ + checkE(100.0*row + col + offset, mx.get(row, col)); + count++; + } + } + checkE(mx.getCols()*mx.getRows(), count); + } + void fillConst(RplMatrix& mx, MatVal value){ + for(int row = 0; row < mx.getRows(); row++){ + for (int col = 0; col < mx.getCols(); col++){ + mx.set(row, col, value); + } + } + } + void checkConst(const RplMatrix& mx, MatVal value){ + int count = 0; + for(int row = 0; row < mx.getRows(); row++){ + for (int col = 0; col < mx.getCols(); col++){ + checkE(value, mx.get(row, col)); + count++; + } + } + checkE(mx.getCols()*mx.getRows(), count); + } + void testBasic() { Tuple2 tuple(-2.0, 0.5); checkE(-2.0, tuple.m_value1); checkE(0.5, tuple.m_value2); - try{ - throw RplMatrixException(1, "String: %s and int %d", "Hi", -333); - checkF(true); - } catch (RplMatrixException exc){ - checkE("String: Hi and int -333", exc.getMessage()); - } RplMatrix mat("mx"); try{ throw RplMatrixException(mat, "String: %s and int %d", "Hi", -333); @@ -37,9 +66,179 @@ public: } catch (RplMatrixException exc){ checkE("String: Hi and int -333", exc.getMessage()); } + checkE("mx", mat.getName()); + checkE("", mat2.getName()); + + RplMatrix m2x3(2, 3, "m2x3"); + checkE("m2x3", m2x3.getName()); + checkE(2, m2x3.getRows()); + checkE(3, m2x3.getCols()); + fillMatrix(m2x3); + checkMatrix(m2x3); + + RplMatrix mxCopy(m2x3); + checkE("m2x3-copy", mxCopy.getName()); + checkE(2, mxCopy.getRows()); + checkE(3, mxCopy.getCols()); + checkMatrix(mxCopy); + + RplMatrix mxCopy2("mxCopy2"); + mxCopy2 = m2x3; + checkE("mxCopy2", mxCopy2.getName()); + checkE(2, mxCopy2.getRows()); + checkE(3, mxCopy2.getCols()); + checkMatrix(mxCopy2); + } + void testAddOperators(){ + RplMatrix m1(3, 2, "m1"); + fillMatrix(m1); + checkMatrix(m1); + RplMatrix m2(3, 2, "m2"); + fillMatrix(m2, 42); + checkMatrix(m2, 42); + RplMatrix m3(3, 2, "m3"); + fillMatrix(m3, -42); + checkMatrix(m3, -42); + + m1 += 42; + checkMatrix(m1, 42); + + checkT(m1 == m2); + checkF(m1 == m3); + + m1 -= 42; + checkMatrix(m1); + m1 -= m1; + checkConst(m1, 0); + + fillMatrix(m1); + m1 -= m3; + checkConst(m1, 42); + m1 += m2; + checkMatrix(m1, 42*2); + } + void testCompareOperators(){ + RplMatrix m1(3, 2, "m1"); + fillMatrix(m1); + checkMatrix(m1); + RplMatrix m2(3, 2, "m2"); + fillMatrix(m2); + + checkT(m1 == m2); + checkF(m1 != m2); + // modify each element, comparism must return false: + int row, col; + for (row = 0; row < m2.getRows(); row++) + for (col = 0; col < m2.getCols(); col++){ + fillMatrix(m2); + m2.set(row, col, -1); + checkF(m1 == m2); + checkT(m1 != m2); + } + + fillConst(m1, 42); + checkT(m1 == 42); + checkF(m1 == 43); + checkT(m1 != 43); + for (row = 0; row < m1.getRows(); row++) + for (col = 0; col < m1.getCols(); col++){ + fillMatrix(m1, 42); + m1.set(row, col, -1); + checkF(m1 == 42); + checkT(m1 != 42); + } + } + + void testCheckDefinition(){ + RplMatrix m1(3, 2, "m1"); + fillMatrix(m1); + checkMatrix(m1); + RplMatrix m2(3, 2, "m2"); + fillMatrix(m2); + + m1.checkDefinition(1, 1); + m1.checkDefinition(1000, 1000); + m1.checkDefinition(0, 0); + try { + m1.checkDefinition(-1, 1); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: row number negative: -1", exc.getMessage()); + } + try { + m1.checkDefinition(1, -1); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: column number negative: -1", exc.getMessage()); + } + + } + void testCheck(){ + RplMatrix m1(3, 2, "m1"); + fillMatrix(m1); + checkMatrix(m1); + + m1.check(0, 0); + m1.check(3-1, 2-1); + try { + m1.check(-1, 1); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: invalid row: -1 not in [0,3[", exc.getMessage()); + } + try { + m1.check(3, 1); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: invalid row: 3 not in [0,3[", exc.getMessage()); + } + try { + m1.check(1, -1); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: invalid column: -1 not in [0,2[", exc.getMessage()); + } + try { + m1.check(1, 2); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: invalid column: 2 not in [0,2[", exc.getMessage()); + } + } + void testCheckSameDimension(){ + RplMatrix m1(3, 2, "m1"); + RplMatrix m2(3, 2, "m2"); + + m1.checkSameDimension(m2); + + m2.resize(2, 2); + try { + m1.checkSameDimension(m2); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: m2 has a different row count: 3 / 2", exc.getMessage()); + } + m2.resize(3, 3); + try { + m1.checkSameDimension(m2); + checkT(false); + } catch(RplMatrixException exc){ + checkE("m1: m2 has a different column count: 2 / 3", exc.getMessage()); + } + log(""); +/* + void checkDefinition(int rows, int cols) const; + void check(int row, int col) const; + void checkSameDimension(const RplMatrix& operand) const; +*/ } - virtual void doIt() { + virtual void doIt(void) { testBasic(); + testAddOperators(); + testCompareOperators(); + testCheckDefinition(); + testCheck(); + testCheckSameDimension(); } }; void testRplMatrix() { diff --git a/unittests/unittests.pro b/unittests/unittests.pro index 5dde07d..3993e6a 100644 --- a/unittests/unittests.pro +++ b/unittests/unittests.pro @@ -18,5 +18,10 @@ TEMPLATE = app SOURCES += main.cpp \ rplmatrix_test.cpp \ - ../rplmath/rplmatrix.cpp + ../rplmath/rplmatrix.cpp \ + ../rplcore/rpllogger.cpp \ + ../rplcore/rpltest.cpp \ + ../rplcore/rplstring.cpp \ + ../rplcore/rplexception.cpp \ + rplexception_test.cpp