summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/global/qlogging
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/global/qlogging')
-rw-r--r--tests/auto/corelib/global/qlogging/app/app.pro3
-rw-r--r--tests/auto/corelib/global/qlogging/app/main.cpp31
-rw-r--r--tests/auto/corelib/global/qlogging/tst_qlogging.cpp260
3 files changed, 202 insertions, 92 deletions
diff --git a/tests/auto/corelib/global/qlogging/app/app.pro b/tests/auto/corelib/global/qlogging/app/app.pro
index 24ac571bac..b11e792a4c 100644
--- a/tests/auto/corelib/global/qlogging/app/app.pro
+++ b/tests/auto/corelib/global/qlogging/app/app.pro
@@ -10,3 +10,6 @@ CONFIG += console
SOURCES += main.cpp
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+gcc:!mingw: QMAKE_LFLAGS += -rdynamic
+
diff --git a/tests/auto/corelib/global/qlogging/app/main.cpp b/tests/auto/corelib/global/qlogging/app/main.cpp
index 621059caad..e190a48873 100644
--- a/tests/auto/corelib/global/qlogging/app/main.cpp
+++ b/tests/auto/corelib/global/qlogging/app/main.cpp
@@ -42,11 +42,37 @@
#include <QCoreApplication>
#include <QLoggingCategory>
+#ifdef Q_CC_GNU
+#define NEVER_INLINE __attribute__((__noinline__))
+#else
+#define NEVER_INLINE
+#endif
+
struct T {
T() { qDebug("static constructor"); }
~T() { qDebug("static destructor"); }
} t;
+class MyClass : public QObject
+{
+ Q_OBJECT
+public slots:
+ virtual NEVER_INLINE QString mySlot1();
+private:
+ virtual NEVER_INLINE void myFunction(int a);
+};
+
+QString MyClass::mySlot1()
+{
+ myFunction(34);
+ return QString();
+}
+
+void MyClass::myFunction(int a)
+{
+ qDebug() << "from_a_function" << a;
+}
+
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
@@ -65,5 +91,10 @@ int main(int argc, char **argv)
qDebug("qDebug2");
+ MyClass cl;
+ QMetaObject::invokeMethod(&cl, "mySlot1");
+
return 0;
}
+
+#include "main.moc"
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
index 21e07630e2..1df5404995 100644
--- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
@@ -63,8 +64,12 @@ private slots:
void cleanupFuncinfo();
#endif
+ void qMessagePattern_data();
void qMessagePattern();
- void qMessagePatternIf();
+ void setMessagePattern();
+
+ void formatLogMessage_data();
+ void formatLogMessage();
private:
QString m_appDir;
@@ -641,11 +646,95 @@ void tst_qmessagehandler::cleanupFuncinfo()
}
#endif
+void tst_qmessagehandler::qMessagePattern_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QList<QByteArray> >("expected");
+
+ // %{file} is tricky because of shadow builds
+ QTest::newRow("basic") << "%{type} %{appname} %{line} %{function} %{message}" << true << (QList<QByteArray>()
+ << "debug 52 T::T static constructor"
+ // we can't be sure whether the QT_MESSAGE_PATTERN is already destructed
+ << "static destructor"
+ << "debug tst_qlogging 73 MyClass::myFunction from_a_function 34"
+ << "debug tst_qlogging 83 main qDebug"
+ << "warning tst_qlogging 84 main qWarning"
+ << "critical tst_qlogging 85 main qCritical"
+ << "warning tst_qlogging 88 main qDebug with category"
+ << "debug tst_qlogging 92 main qDebug2");
+
+
+ QTest::newRow("invalid") << "PREFIX: %{unknown} %{message}" << false << (QList<QByteArray>()
+ << "QT_MESSAGE_PATTERN: Unknown placeholder %{unknown}"
+ << "PREFIX: qDebug");
+
+ // test the if condition
+ QTest::newRow("ifs") << "[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{if-category}%{category}: %{endif}%{message}"
+ << true << (QList<QByteArray>()
+ << "[D] static constructor"
+ // we can't be sure whether the QT_MESSAGE_PATTERN is already destructed
+ << "static destructor"
+ << "[D] qDebug"
+ << "[W] qWarning"
+ << "[C] qCritical"
+ << "[W] category: qDebug with category"
+ << "[D] qDebug2");
+
+ // test few errors cases
+ QTest::newRow("ifs-invalid1") << "PREFIX: %{unknown} %{endif} %{if-warning}"
+ << false << (QList<QByteArray>()
+ << "QT_MESSAGE_PATTERN: Unknown placeholder %{unknown}"
+ << "QT_MESSAGE_PATTERN: %{endif} without an %{if-*}"
+ << "QT_MESSAGE_PATTERN: missing %{endif}");
+
+ QTest::newRow("ifs-invalid2") << "A %{if-debug}DEBUG%{if-warning}WARNING%{endif} %{message} "
+ << false << (QList<QByteArray>()
+ << "QT_MESSAGE_PATTERN: %{if-*} cannot be nested"
+ << "A DEBUG qDebug "
+ << "A qWarning ");
+
+ // This test won't work when midnight is too close... wait a bit
+ while (QTime::currentTime() > QTime(23, 59, 30))
+ QTest::qWait(10000);
+ QTest::newRow("time") << "/%{time yyyy - MM - d}/%{message}"
+ << true << (QList<QByteArray>()
+ << ('/' + QDateTime::currentDateTime().toString("yyyy - MM - d").toUtf8() + "/qDebug"));
+
+ // %{time} should have a padding of 6 so if it takes less than 10 seconds to show
+ // the first message, there should be 5 spaces
+ QTest::newRow("time") << "<%{time}>%{message}" << true << (QList<QByteArray>()
+ << "< ");
+
+#ifdef __GLIBC__
+#ifdef QT_NAMESPACE
+#define QT_NAMESPACE_STR QT_STRINGIFY(QT_NAMESPACE::)
+#else
+#define QT_NAMESPACE_STR ""
+#endif
+
+#ifndef QT_NO_DEBUG
+ QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << (QList<QByteArray>()
+ // MyClass::qt_static_metacall is explicitly marked as hidden in the Q_OBJECT macro
+ << "[MyClass::myFunction|MyClass::mySlot1|?app?|" QT_NAMESPACE_STR "QMetaMethod::invoke|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34");
+#endif
+
+ QTest::newRow("backtrace depth,separator") << "[%{backtrace depth=2 separator=\"\n\"}] %{message}" << true << (QList<QByteArray>()
+ << "[MyClass::myFunction\nMyClass::mySlot1] from_a_function 34");
+#endif
+
+}
+
+
void tst_qmessagehandler::qMessagePattern()
{
#ifdef QT_NO_PROCESS
QSKIP("This test requires QProcess support");
#else
+ QFETCH(QString, pattern);
+ QFETCH(bool, valid);
+ QFETCH(QList<QByteArray>, expected);
+
QProcess process;
const QString appExe = m_appDir + "/app";
@@ -653,8 +742,7 @@ void tst_qmessagehandler::qMessagePattern()
// test QT_MESSAGE_PATTERN
//
QStringList environment = m_baseEnvironment;
- // %{file} is tricky because of shadow builds
- environment.prepend("QT_MESSAGE_PATTERN=\"%{type} %{appname} %{line} %{function} %{message}\"");
+ environment.prepend("QT_MESSAGE_PATTERN=\"" + pattern + "\"");
process.setEnvironment(environment);
process.start(appExe);
@@ -665,35 +753,33 @@ void tst_qmessagehandler::qMessagePattern()
QByteArray output = process.readAllStandardError();
// qDebug() << output;
QVERIFY(!output.isEmpty());
+ QCOMPARE(!output.contains("QT_MESSAGE_PATTERN"), valid);
- QVERIFY(output.contains("debug 46 T::T static constructor"));
- // we can't be sure whether the QT_MESSAGE_PATTERN is already destructed
- QVERIFY(output.contains("static destructor"));
- QVERIFY(output.contains("debug tst_qlogging 57 main qDebug"));
- QVERIFY(output.contains("warning tst_qlogging 58 main qWarning"));
- QVERIFY(output.contains("critical tst_qlogging 59 main qCritical"));
- QVERIFY(output.contains("warning tst_qlogging 62 main qDebug with category"));
- QVERIFY(output.contains("debug tst_qlogging 66 main qDebug2"));
-
- environment = m_baseEnvironment;
- environment.prepend("QT_MESSAGE_PATTERN=\"PREFIX: %{unknown} %{message}\"");
- process.setEnvironment(environment);
-
- process.start(appExe);
- QVERIFY2(process.waitForStarted(), qPrintable(
- QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString())));
- process.waitForFinished();
-
- output = process.readAllStandardError();
-// qDebug() << output;
- QVERIFY(!output.isEmpty());
+ foreach (const QByteArray &e, expected) {
+ if (!output.contains(e)) {
+ qDebug() << output;
+ qDebug() << "expected: " << e;
+ QVERIFY(output.contains(e));
+ }
+ }
+#endif
+}
- QVERIFY(output.contains("QT_MESSAGE_PATTERN: Unknown placeholder %{unknown}"));
- QVERIFY(output.contains("PREFIX: qDebug"));
+void tst_qmessagehandler::setMessagePattern()
+{
+#ifdef QT_NO_PROCESS
+ QSKIP("This test requires QProcess support");
+#else
//
// test qSetMessagePattern
//
+
+ QProcess process;
+ const QString appExe = m_appDir + "/app";
+
+ // make sure there is no QT_MESSAGE_PATTERN in the environment
+ QStringList environment = m_baseEnvironment;
QMutableListIterator<QString> iter(environment);
while (iter.hasNext()) {
if (iter.next().startsWith("QT_MESSAGE_PATTERN"))
@@ -706,7 +792,7 @@ void tst_qmessagehandler::qMessagePattern()
QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString())));
process.waitForFinished();
- output = process.readAllStandardError();
+ QByteArray output = process.readAllStandardError();
//qDebug() << output;
QByteArray expected = "static constructor\n"
"[debug] qDebug\n"
@@ -720,73 +806,63 @@ void tst_qmessagehandler::qMessagePattern()
#endif // !QT_NO_PROCESS
}
-void tst_qmessagehandler::qMessagePatternIf()
-{
-#ifdef QT_NO_PROCESS
- QSKIP("This test requires QProcess support");
-#else
- QProcess process;
- const QString appExe = m_appDir + "/app";
-
- QStringList environment = m_baseEnvironment;
- environment.prepend("QT_MESSAGE_PATTERN=\"[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{if-category}%{category}: %{endif}%{message}\"");
- process.setEnvironment(environment);
- process.start(appExe);
- QVERIFY2(process.waitForStarted(), qPrintable(
- QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString())));
- process.waitForFinished();
-
- QByteArray output = process.readAllStandardError();
- // qDebug() << output;
- QVERIFY(!output.isEmpty());
- QVERIFY(!output.contains("QT_MESSAGE_PATTERN"));
-
- QVERIFY(output.contains("[D] static constructor"));
- // we can't be sure whether the QT_MESSAGE_PATTERN is already destructed
- QVERIFY(output.contains("static destructor"));
- QVERIFY(output.contains("[D] qDebug"));
- QVERIFY(output.contains("[W] qWarning"));
- QVERIFY(output.contains("[C] qCritical"));
- QVERIFY(output.contains("[W] category: qDebug with category"));
- QVERIFY(output.contains("[D] qDebug2"));
+Q_DECLARE_METATYPE(QtMsgType)
- //
- // Tests some errors
- //
- environment = m_baseEnvironment;
- environment.prepend("QT_MESSAGE_PATTERN=\"PREFIX: %{unknown} %{endif} %{if-warning}\"");
- process.setEnvironment(environment);
-
- process.start(appExe);
- QVERIFY2(process.waitForStarted(), qPrintable(
- QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString())));
- process.waitForFinished();
-
- output = process.readAllStandardError();
- // qDebug() << output;
- QVERIFY(!output.isEmpty());
- QVERIFY(output.contains("QT_MESSAGE_PATTERN: Unknown placeholder %{unknown}"));
- QVERIFY(output.contains("QT_MESSAGE_PATTERN: %{endif} without an %{if-*}"));
- QVERIFY(output.contains("QT_MESSAGE_PATTERN: missing %{endif}"));
-
-
- environment = m_baseEnvironment;
- environment.prepend("QT_MESSAGE_PATTERN=\"A %{if-debug}DEBUG%{if-warning}WARNING%{endif} %{message} \"");
- process.setEnvironment(environment);
-
- process.start(appExe);
- QVERIFY2(process.waitForStarted(), qPrintable(
- QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString())));
- process.waitForFinished();
+void tst_qmessagehandler::formatLogMessage_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QString>("result");
+
+ QTest::addColumn<QtMsgType>("type");
+ QTest::addColumn<QByteArray>("file");
+ QTest::addColumn<int>("line");
+ QTest::addColumn<QByteArray>("function");
+ QTest::addColumn<QByteArray>("category");
+ QTest::addColumn<QString>("message");
+
+#define BA QByteArrayLiteral
+
+ QTest::newRow("basic") << "%{type} %{file} %{line} %{function} %{message}"
+ << "debug main.cpp 1 func msg\n"
+ << QtDebugMsg << BA("main.cpp") << 1 << BA("func") << BA("") << "msg";
+
+ // test the if conditions
+ QString format = "[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{if-category}%{category}: %{endif}%{message}";
+ QTest::newRow("if-debug")
+ << format << "[D] msg\n"
+ << QtDebugMsg << BA("") << 0 << BA("func") << QByteArray() << "msg";
+ QTest::newRow("if_warning")
+ << format << "[W] msg\n"
+ << QtWarningMsg << BA("") << 0 << BA("func") << QByteArray() << "msg";
+ QTest::newRow("if_critical")
+ << format << "[C] msg\n"
+ << QtCriticalMsg << BA("") << 0 << BA("func") << QByteArray() << "msg";
+ QTest::newRow("if_fatal")
+ << format << "[F] msg\n"
+ << QtFatalMsg << BA("") << 0 << BA("func") << QByteArray() << "msg";
+ QTest::newRow("if_cat")
+ << format << "[F] cat: msg\n"
+ << QtFatalMsg << BA("") << 0 << BA("func") << BA("cat") << "msg";
+}
- output = process.readAllStandardError();
- // qDebug() << output;
- QVERIFY(!output.isEmpty());
- QVERIFY(output.contains("QT_MESSAGE_PATTERN: %{if-*} cannot be nested"));
- QVERIFY(output.contains("A DEBUG qDebug"));
- QVERIFY(output.contains("A qWarning"));
-#endif // !QT_NO_PROCESS
+void tst_qmessagehandler::formatLogMessage()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QString, result);
+
+ QFETCH(QtMsgType, type);
+ QFETCH(QByteArray, file);
+ QFETCH(int, line);
+ QFETCH(QByteArray, function);
+ QFETCH(QByteArray, category);
+ QFETCH(QString, message);
+
+ qSetMessagePattern(pattern);
+ QMessageLogContext ctxt(file, line, function, category.isEmpty() ? 0 : category.data());
+ QString r = qFormatLogMessage(type, ctxt, message);
+ QCOMPARE(r, result);
}
+
QTEST_MAIN(tst_qmessagehandler)
#include "tst_qlogging.moc"