From 943ae8bb701a8187d295b747ba82025c55ca9add Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 12 Nov 2013 15:03:54 +0100 Subject: [PATCH] Add overload of QTest::ignoreMessage() taking a QRegularExpression. Make it possible to match messages by a pattern. Change-Id: I713312e86db5471755459f1ecc43e8f1ac7a95fb Reviewed-by: Jason McDonald --- src/testlib/qtestcase.cpp | 21 +++++++ src/testlib/qtestcase.h | 2 + src/testlib/qtestlog.cpp | 59 +++++++++++++------ src/testlib/qtestlog_p.h | 2 + .../selftests/expected_warnings.lightxml | 14 +++++ .../testlib/selftests/expected_warnings.txt | 6 +- .../testlib/selftests/expected_warnings.xml | 14 +++++ .../selftests/expected_warnings.xunitxml | 11 +++- .../selftests/warnings/tst_warnings.cpp | 17 ++++++ 9 files changed, 127 insertions(+), 19 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 755720a98c4..b09bd6701c8 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2332,6 +2332,27 @@ void QTest::ignoreMessage(QtMsgType type, const char *message) QTestLog::ignoreMessage(type, message); } +/*! + \overload + + Ignores messages created by qDebug() or qWarning(). If the \a message + matching \a messagePattern + with the corresponding \a type is outputted, it will be removed from the + test log. If the test finished and the \a message was not outputted, + a test failure is appended to the test log. + + \b {Note:} Invoking this function will only ignore one message. + If the message you want to ignore is outputted twice, you have to + call ignoreMessage() twice, too. + + \since 5.3 +*/ + +void QTest::ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern) +{ + QTestLog::ignoreMessage(type, messagePattern); +} + /*! \internal */ diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index ba727b5afe9..2a5d7d353b0 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -53,6 +53,7 @@ QT_BEGIN_NAMESPACE +class QRegularExpression; #define QVERIFY(statement) \ do {\ @@ -191,6 +192,7 @@ namespace QTest const char *file, int line); Q_TESTLIB_EXPORT void qWarn(const char *message, const char *file = 0, int line = 0); Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message); + Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const QRegularExpression &messagePattern); Q_TESTLIB_EXPORT QString qFindTestData(const char* basepath, const char* file = 0, int line = 0, const char* builddir = 0); Q_TESTLIB_EXPORT QString qFindTestData(const QString& basepath, const char* file = 0, int line = 0, const char* builddir = 0); diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 5b6cbe658cd..d0cc3895c38 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include #include @@ -84,11 +86,8 @@ namespace QTest { struct IgnoreResultList { - inline IgnoreResultList(QtMsgType tp, const char *message) - : type(tp), next(0) - { msg = qstrdup(message); } - inline ~IgnoreResultList() - { delete [] msg; } + inline IgnoreResultList(QtMsgType tp, const QVariant &patternIn) + : type(tp), pattern(patternIn), next(0) {} static inline void clearList(IgnoreResultList *&list) { @@ -99,8 +98,29 @@ namespace QTest { } } + static void append(IgnoreResultList *&list, QtMsgType type, const QVariant &patternIn) + { + QTest::IgnoreResultList *item = new QTest::IgnoreResultList(type, patternIn); + + if (!list) { + list = item; + return; + } + IgnoreResultList *last = list; + for ( ; last->next; last = last->next) ; + last->next = item; + } + + inline bool matches(QtMsgType tp, const QString &message) const + { + return tp == type + && (pattern.type() == QVariant::String ? + pattern.toString() == message : + pattern.toRegularExpression().match(message).hasMatch()); + } + QtMsgType type; - char *msg; + QVariant pattern; IgnoreResultList *next; }; @@ -208,10 +228,13 @@ namespace QTest { static bool handleIgnoredMessage(QtMsgType type, const char *msg) { + if (!ignoreResultList) + return false; + const QString message = QString::fromLocal8Bit(msg); IgnoreResultList *last = 0; IgnoreResultList *list = ignoreResultList; while (list) { - if (list->type == type && strcmp(msg, list->msg) == 0) { + if (list->matches(type, message)) { // remove the item from the list if (last) last->next = list->next; @@ -316,7 +339,11 @@ void QTestLog::printUnhandledIgnoreMessages() char msg[1024]; QTest::IgnoreResultList *list = QTest::ignoreResultList; while (list) { - qsnprintf(msg, 1024, "Did not receive message: \"%s\"", list->msg); + if (list->pattern.type() == QVariant::String) { + qsnprintf(msg, 1024, "Did not receive message: \"%s\"", qPrintable(list->pattern.toString())); + } else { + qsnprintf(msg, 1024, "Did not receive any message matching: \"%s\"", qPrintable(list->pattern.toRegularExpression().pattern())); + } QTest::TestLoggers::addMessage(QAbstractTestLogger::Info, msg); list = list->next; @@ -462,16 +489,14 @@ void QTestLog::ignoreMessage(QtMsgType type, const char *msg) { QTEST_ASSERT(msg); - QTest::IgnoreResultList *item = new QTest::IgnoreResultList(type, msg); + QTest::IgnoreResultList::append(QTest::ignoreResultList, type, QString::fromLocal8Bit(msg)); +} - QTest::IgnoreResultList *list = QTest::ignoreResultList; - if (!list) { - QTest::ignoreResultList = item; - return; - } - while (list->next) - list = list->next; - list->next = item; +void QTestLog::ignoreMessage(QtMsgType type, const QRegularExpression &expression) +{ + QTEST_ASSERT(expression.isValid()); + + QTest::IgnoreResultList::append(QTest::ignoreResultList, type, QVariant(expression)); } void QTestLog::setMaxWarnings(int m) diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index df3e2ab5d4a..bd838709345 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE class QBenchmarkResult; +class QRegularExpression; class Q_TESTLIB_EXPORT QTestLog { @@ -75,6 +76,7 @@ public: static void addBenchmarkResult(const QBenchmarkResult &result); static void ignoreMessage(QtMsgType type, const char *msg); + static void ignoreMessage(QtMsgType type, const QRegularExpression &expression); static int unhandledIgnoreMessages(); static void printUnhandledIgnoreMessages(); static void clearIgnoreMessages(); diff --git a/tests/auto/testlib/selftests/expected_warnings.lightxml b/tests/auto/testlib/selftests/expected_warnings.lightxml index ad786832ca4..2ad9e974498 100644 --- a/tests/auto/testlib/selftests/expected_warnings.lightxml +++ b/tests/auto/testlib/selftests/expected_warnings.lightxml @@ -24,6 +24,12 @@ + + + + + + @@ -37,6 +43,14 @@ + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_warnings.txt b/tests/auto/testlib/selftests/expected_warnings.txt index d8064651b0c..e73de980cb9 100644 --- a/tests/auto/testlib/selftests/expected_warnings.txt +++ b/tests/auto/testlib/selftests/expected_warnings.txt @@ -7,10 +7,14 @@ QDEBUG : tst_Warnings::testWarnings() Debug QDEBUG : tst_Warnings::testWarnings() Debug QDEBUG : tst_Warnings::testWarnings() Baba QDEBUG : tst_Warnings::testWarnings() Baba +QDEBUG : tst_Warnings::testWarnings() Bubublabla +QWARN : tst_Warnings::testWarnings() Babablabla PASS : tst_Warnings::testWarnings() INFO : tst_Warnings::testMissingWarnings() Did not receive message: "Warning0" INFO : tst_Warnings::testMissingWarnings() Did not receive message: "Warning1" FAIL! : tst_Warnings::testMissingWarnings() Not all expected messages were received +INFO : tst_Warnings::testMissingWarningsRegularExpression() Did not receive any message matching: "Warning\s\d" +FAIL! : tst_Warnings::testMissingWarningsRegularExpression() Not all expected messages were received INFO : tst_Warnings::testMissingWarningsWithData(first row) Did not receive message: "Warning0" INFO : tst_Warnings::testMissingWarningsWithData(first row) Did not receive message: "Warning1" FAIL! : tst_Warnings::testMissingWarningsWithData(first row) Not all expected messages were received @@ -18,5 +22,5 @@ INFO : tst_Warnings::testMissingWarningsWithData(second row) Did not receive m INFO : tst_Warnings::testMissingWarningsWithData(second row) Did not receive message: "Warning1" FAIL! : tst_Warnings::testMissingWarningsWithData(second row) Not all expected messages were received PASS : tst_Warnings::cleanupTestCase() -Totals: 3 passed, 3 failed, 0 skipped +Totals: 3 passed, 4 failed, 0 skipped ********* Finished testing of tst_Warnings ********* diff --git a/tests/auto/testlib/selftests/expected_warnings.xml b/tests/auto/testlib/selftests/expected_warnings.xml index 8ad236b52a2..14a45ca4fd8 100644 --- a/tests/auto/testlib/selftests/expected_warnings.xml +++ b/tests/auto/testlib/selftests/expected_warnings.xml @@ -26,6 +26,12 @@ + + + + + + @@ -39,6 +45,14 @@ + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_warnings.xunitxml b/tests/auto/testlib/selftests/expected_warnings.xunitxml index 3e3b9ce18ea..7be47174c61 100644 --- a/tests/auto/testlib/selftests/expected_warnings.xunitxml +++ b/tests/auto/testlib/selftests/expected_warnings.xunitxml @@ -1,5 +1,5 @@ - + @@ -12,12 +12,18 @@ + + + + + + @@ -34,8 +40,11 @@ + + + diff --git a/tests/auto/testlib/selftests/warnings/tst_warnings.cpp b/tests/auto/testlib/selftests/warnings/tst_warnings.cpp index 20f53fdc916..ff4357f11f9 100644 --- a/tests/auto/testlib/selftests/warnings/tst_warnings.cpp +++ b/tests/auto/testlib/selftests/warnings/tst_warnings.cpp @@ -41,6 +41,7 @@ #include +#include #include class tst_Warnings: public QObject @@ -49,6 +50,7 @@ class tst_Warnings: public QObject private slots: void testWarnings(); void testMissingWarnings(); + void testMissingWarningsRegularExpression(); void testMissingWarningsWithData_data(); void testMissingWarningsWithData(); }; @@ -73,6 +75,13 @@ void tst_Warnings::testWarnings() qDebug("Baba"); qDebug("Bubu"); qDebug("Baba"); + + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("^Bubu.*")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("^Baba.*")); + qDebug("Bubublabla"); + qWarning("Babablabla"); + qDebug("Bubublabla"); + qWarning("Babablabla"); } void tst_Warnings::testMissingWarnings() @@ -84,6 +93,14 @@ void tst_Warnings::testMissingWarnings() qWarning("Warning2"); } +void tst_Warnings::testMissingWarningsRegularExpression() +{ + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Warning\\d\\d")); + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Warning\\s\\d")); + + qWarning("Warning11"); +} + void tst_Warnings::testMissingWarningsWithData_data() { QTest::addColumn("dummy");