summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qmake/Makefile.unix6
-rw-r--r--qmake/Makefile.win324
-rw-r--r--qmake/Makefile.win32-g++5
-rw-r--r--qmake/Makefile.win32-g++-sh6
-rw-r--r--qmake/qmake.pri3
-rw-r--r--src/corelib/global/qglobal.cpp21
-rw-r--r--src/corelib/global/qlogging.cpp313
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp24
-rw-r--r--tests/auto/corelib/global/global.pro2
-rw-r--r--tests/auto/corelib/global/qlogging/app/app.pro9
-rw-r--r--tests/auto/corelib/global/qlogging/app/main.cpp55
-rw-r--r--tests/auto/corelib/global/qlogging/qlogging.pro5
-rw-r--r--tests/auto/corelib/global/qlogging/tst_qlogging.cpp645
-rw-r--r--tests/auto/corelib/global/qlogging/tst_qlogging.pro4
-rw-r--r--tests/auto/corelib/global/qmessagehandler/qmessagehandler.pro4
-rw-r--r--tests/auto/corelib/global/qmessagehandler/tst_qmessagehandler.cpp147
-rw-r--r--tools/configure/configure.pro2
17 files changed, 1076 insertions, 179 deletions
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index 286e2ebcbc..16af49311b 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -22,7 +22,7 @@ QOBJS=qtextcodec.o qutfcodec.o qstring.o qtextstream.o qiodevice.o qmalloc.o qgl
qfileinfo.o qdatetime.o qstringlist.o qabstractfileengine.o qtemporaryfile.o \
qmap.o qmetatype.o qsettings.o qsystemerror.o qlibraryinfo.o qvariant.o qvsnprintf.o \
qlocale.o qlocale_tools.o qlocale_unix.o qlinkedlist.o qurl.o qnumeric.o qcryptographichash.o \
- qxmlstream.o qxmlutils.o \
+ qxmlstream.o qxmlutils.o qlogging.o \
$(QTOBJS)
@@ -66,6 +66,7 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge
$(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \
$(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \
$(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
$(QTSRCS)
CPPFLAGS = -g -I. -Igenerators -Igenerators/unix -Igenerators/win32 \
@@ -316,6 +317,9 @@ qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
+qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
+
#default rules
.cpp.o:
$(CXX) -c -o $@ $(CXXFLAGS) $<
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index e767786001..3efe6a67e0 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -118,8 +118,8 @@ QTOBJS= \
qmetatype.obj \
qxmlstream.obj \
qxmlutils.obj \
- qnumeric.obj
-
+ qnumeric.obj \
+ qlogging.obj
first all: qmake.exe
diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++
index 443dba390a..585061ed26 100644
--- a/qmake/Makefile.win32-g++
+++ b/qmake/Makefile.win32-g++
@@ -95,7 +95,8 @@ QTOBJS= \
qmetatype.o \
qxmlstream.o \
qxmlutils.o \
- qnumeric.o
+ qnumeric.o \
+ qlogging.o
qmake.exe: $(OBJS) $(QTOBJS)
@@ -339,3 +340,5 @@ qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
$(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
+qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
+ $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
diff --git a/qmake/Makefile.win32-g++-sh b/qmake/Makefile.win32-g++-sh
index bc8356e178..6dfb486375 100644
--- a/qmake/Makefile.win32-g++-sh
+++ b/qmake/Makefile.win32-g++-sh
@@ -95,7 +95,8 @@ QTOBJS= \
qmetatype.o \
qxmlstream.o \
qxmlutils.o \
- qnumeric.o
+ qnumeric.o \
+ qlogging.o
qmake.exe: $(OBJS) $(QTOBJS)
$(LINKQMAKE)
@@ -337,3 +338,6 @@ qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
$(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
+
+qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
+ $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
diff --git a/qmake/qmake.pri b/qmake/qmake.pri
index 1f59531c42..ba6ab383c7 100644
--- a/qmake/qmake.pri
+++ b/qmake/qmake.pri
@@ -76,7 +76,8 @@ bootstrap { #Qt code
qvector.cpp \
qvsnprintf.cpp \
qxmlstream.cpp \
- qxmlutils.cpp
+ qxmlutils.cpp \
+ qlogging.cpp
HEADERS+= \
qbitarray.h \
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 01b3e2ec32..983116f1b3 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1862,27 +1862,32 @@ extern Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogConte
const char *str);
#endif
+// defined in qlogging.cpp
+extern Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogContext &context,
+ const char *str);
+
/*!
\internal
*/
-static void qDefaultMsgHandler(QtMsgType, const char *buf)
+static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, const char *buf)
{
+ QByteArray logMessage = qMessageFormatString(type, context, buf);
#if defined(Q_OS_WINCE)
- QString fstr = QString::fromLatin1(buf);
- fstr += QLatin1Char('\n');
- OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
+ QString fstr = QString::fromLocal8Bit(logMessage);
+ OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
#else
- fprintf(stderr, "%s\n", buf);
- fflush(stderr);
+ fprintf(stderr, "%s", logMessage.constData());
+ fflush(stderr);
#endif
}
/*!
\internal
*/
-static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &, const char *buf)
+static void qDefaultMsgHandler(QtMsgType type, const char *buf)
{
- qDefaultMsgHandler(type, buf);
+ QMessageLogContext emptyContext;
+ qDefaultMessageHandler(type, emptyContext, buf);
}
QMessageHandler qInstallMessageHandler(QMessageHandler h)
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index bc26c9b6b7..39b3205571 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -39,7 +39,13 @@
**
****************************************************************************/
-#include <qlogging.h>
+#include "qlogging.h"
+#include "qlist.h"
+#include "qbytearray.h"
+#include "qstring.h"
+#include "qvarlengtharray.h"
+
+#include <stdio.h>
QT_BEGIN_NAMESPACE
@@ -73,4 +79,309 @@ QT_BEGIN_NAMESPACE
\sa QMessageLogContext, qDebug(), qWarning(), qCritical(), qFatal()
*/
+/*!
+ \internal
+*/
+Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
+{
+ // Strip the function info down to the base function name
+ // note that this throws away the template definitions,
+ // the parameter types (overloads) and any const/volatile qualifiers.
+
+ if (info.isEmpty())
+ return info;
+
+ int pos;
+
+ // skip trailing [with XXX] for templates (gcc)
+ pos = info.size() - 1;
+ if (info.endsWith(']')) {
+ while (--pos) {
+ if (info.at(pos) == '[')
+ info.truncate(pos);
+ }
+ }
+
+ // operator names with '(', ')', '<', '>' in it
+ static const char operator_call[] = "operator()";
+ static const char operator_lessThan[] = "operator<";
+ static const char operator_greaterThan[] = "operator>";
+ static const char operator_lessThanEqual[] = "operator<=";
+ static const char operator_greaterThanEqual[] = "operator>=";
+
+ // canonize operator names
+ info.replace("operator ", "operator");
+
+ // remove argument list
+ forever {
+ int parencount = 0;
+ pos = info.lastIndexOf(')');
+ if (pos == -1) {
+ // Don't know how to parse this function name
+ return info;
+ }
+
+ // find the beginning of the argument list
+ --pos;
+ ++parencount;
+ while (pos && parencount) {
+ if (info.at(pos) == ')')
+ ++parencount;
+ else if (info.at(pos) == '(')
+ --parencount;
+ --pos;
+ }
+ if (parencount != 0)
+ return info;
+
+ info.truncate(++pos);
+
+ if (info.at(pos - 1) == ')') {
+ if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
+ break;
+
+ // this function returns a pointer to a function
+ // and we matched the arguments of the return type's parameter list
+ // try again
+ info.remove(0, info.indexOf('('));
+ info.chop(1);
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ // find the beginning of the function name
+ int parencount = 0;
+ int templatecount = 0;
+ --pos;
+
+ // make sure special characters in operator names are kept
+ if (pos > -1) {
+ switch (info.at(pos)) {
+ case ')':
+ if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
+ pos -= 2;
+ break;
+ case '<':
+ if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
+ --pos;
+ break;
+ case '>':
+ if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
+ --pos;
+ break;
+ case '=': {
+ int operatorLength = (int)strlen(operator_lessThanEqual);
+ if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
+ pos -= 2;
+ else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
+ pos -= 2;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ while (pos > -1) {
+ if (parencount < 0 || templatecount < 0)
+ return info;
+
+ char c = info.at(pos);
+ if (c == ')')
+ ++parencount;
+ else if (c == '(')
+ --parencount;
+ else if (c == '>')
+ ++templatecount;
+ else if (c == '<')
+ --templatecount;
+ else if (c == ' ' && templatecount == 0 && parencount == 0)
+ break;
+
+ --pos;
+ }
+ info = info.mid(pos + 1);
+
+ // we have the full function name now.
+ // clean up the templates
+ while ((pos = info.lastIndexOf('>')) != -1) {
+ if (!info.contains('<'))
+ break;
+
+ // find the matching close
+ int end = pos;
+ templatecount = 1;
+ --pos;
+ while (pos && templatecount) {
+ register char c = info.at(pos);
+ if (c == '>')
+ ++templatecount;
+ else if (c == '<')
+ --templatecount;
+ --pos;
+ }
+ ++pos;
+ info.remove(pos, end - pos + 1);
+ }
+
+ return info;
+}
+
+// tokens as recognized in QT_MESSAGE_PATTERN
+static const char typeTokenC[] = "%{type}";
+static const char messageTokenC[] = "%{message}";
+static const char fileTokenC[] = "%{file}";
+static const char lineTokenC[] = "%{line}";
+static const char functionTokenC[] = "%{function}";
+static const char emptyTokenC[] = "";
+
+struct QMessagePattern {
+ QMessagePattern();
+ ~QMessagePattern();
+
+ // 0 terminated arrays of literal tokens / literal or placeholder tokens
+ const char **literals;
+ const char **tokens;
+};
+
+QMessagePattern::QMessagePattern()
+{
+ QString pattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
+ if (pattern.isEmpty()) {
+ pattern = QLatin1String("%{message}");
+ }
+
+ // scanner
+ QList<QString> lexemes;
+ QString lexeme;
+ bool inPlaceholder = false;
+ for (int i = 0; i < pattern.size(); ++i) {
+ const QChar c = pattern.at(i);
+ if ((c == QLatin1Char('%'))
+ && !inPlaceholder) {
+ if ((i + 1 < pattern.size())
+ && pattern.at(i + 1) == QLatin1Char('{')) {
+ // beginning of placeholder
+ if (!lexeme.isEmpty()) {
+ lexemes.append(lexeme);
+ lexeme.clear();
+ }
+ inPlaceholder = true;
+ }
+ }
+
+ lexeme.append(c);
+
+ if ((c == QLatin1Char('}') && inPlaceholder)) {
+ // end of placeholder
+ lexemes.append(lexeme);
+ lexeme.clear();
+ inPlaceholder = false;
+ }
+ }
+ if (!lexeme.isEmpty())
+ lexemes.append(lexeme);
+
+ // tokenizer
+ QVarLengthArray<const char*> literalsVar;
+ tokens = new const char*[lexemes.size() + 1];
+ tokens[lexemes.size()] = 0;
+
+ for (int i = 0; i < lexemes.size(); ++i) {
+ const QString lexeme = lexemes.at(i);
+ if (lexeme.startsWith(QLatin1String("%{"))
+ && lexeme.endsWith(QLatin1Char('}'))) {
+ // placeholder
+ if (lexeme == QLatin1String(typeTokenC)) {
+ tokens[i] = typeTokenC;
+ } else if (lexeme == QLatin1String(messageTokenC))
+ tokens[i] = messageTokenC;
+ else if (lexeme == QLatin1String(fileTokenC))
+ tokens[i] = fileTokenC;
+ else if (lexeme == QLatin1String(lineTokenC))
+ tokens[i] = lineTokenC;
+ else if (lexeme == QLatin1String(functionTokenC))
+ tokens[i] = functionTokenC;
+ else {
+ fprintf(stderr, "%s\n",
+ QString::fromLatin1("QT_MESSAGE_PATTERN: Unknown placeholder %1\n"
+ ).arg(lexeme).toLocal8Bit().constData());
+ fflush(stderr);
+ tokens[i] = emptyTokenC;
+ }
+ } else {
+ char *literal = new char[lexeme.size() + 1];
+ strncpy(literal, lexeme.toLocal8Bit().constData(), lexeme.size());
+ literal[lexeme.size()] = '\0';
+ literalsVar.append(literal);
+ tokens[i] = literal;
+ }
+ }
+ literals = new const char*[literalsVar.size() + 1];
+ literals[literalsVar.size()] = 0;
+ memcpy(literals, literalsVar.constData(), literalsVar.size() * sizeof(const char*));
+}
+
+QMessagePattern::~QMessagePattern()
+{
+ for (int i = 0; literals[i] != 0; ++i)
+ delete [] literals[i];
+ delete [] literals;
+ literals = 0;
+ delete [] tokens;
+ tokens = 0;
+}
+
+Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern)
+
+/*!
+ \internal
+*/
+Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogContext &context,
+ const char *str)
+{
+ QByteArray message;
+
+ QMessagePattern *pattern = qMessagePattern();
+ if (!pattern) {
+ // after destruction of static QMessagePattern instance
+ message.append(str);
+ message.append('\n');
+ return message;
+ }
+
+ // we do not convert file, function, line literals to local encoding due to overhead
+ for (int i = 0; pattern->tokens[i] != 0; ++i) {
+ const char *token = pattern->tokens[i];
+ if (token == messageTokenC) {
+ message.append(str);
+ } else if (token == typeTokenC) {
+ switch (type) {
+ case QtDebugMsg: message.append("debug"); break;
+ case QtWarningMsg: message.append("warning"); break;
+ case QtCriticalMsg:message.append("critical"); break;
+ case QtFatalMsg: message.append("fatal"); break;
+ }
+ } else if (token == fileTokenC) {
+ if (context.file)
+ message.append(context.file);
+ else
+ message.append("unknown");
+ } else if (token == lineTokenC) {
+ message.append(QString::number(context.line).toLatin1().constData());
+ } else if (token == functionTokenC) {
+ if (context.function)
+ message.append(qCleanupFuncinfo(context.function));
+ else
+ message.append("unknown");
+ } else {
+ message.append(token);
+ }
+ }
+ message.append('\n');
+ return message;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 9a45f28f16..c1f7c8ab25 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -140,30 +140,30 @@ public:
{ LeaveCriticalSection(&cs); }
};
-Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str)
-{
- Q_UNUSED(t);
- // OutputDebugString is not threadsafe.
+// defined in qlogging.cpp
+extern Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type,
+ const QMessageLogContext &context,
+ const char *str);
+Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &context, const char *str)
+{
// cannot use QMutex here, because qWarning()s in the QMutex
// implementation may cause this function to recurse
static QWinMsgHandlerCriticalSection staticCriticalSection;
- if (!str)
- str = "(null)";
+ QByteArray message = qMessageFormatString(t, context, str);
+ QString s(QString::fromLocal8Bit(message));
+ // OutputDebugString is not threadsafe.
staticCriticalSection.lock();
-
- QString s(QString::fromLocal8Bit(str));
- s += QLatin1Char('\n');
OutputDebugString((wchar_t*)s.utf16());
-
staticCriticalSection.unlock();
}
-Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &, const char* str)
+Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char *str)
{
- qWinMsgHandler(t, str);
+ QMessageLogContext emptyContext;
+ qWinMessageHandler(t, emptyContext, str);
}
/*****************************************************************************
diff --git a/tests/auto/corelib/global/global.pro b/tests/auto/corelib/global/global.pro
index a6c638f530..d4293a896c 100644
--- a/tests/auto/corelib/global/global.pro
+++ b/tests/auto/corelib/global/global.pro
@@ -6,4 +6,4 @@ SUBDIRS=\
qglobal \
qnumeric \
qrand \
- qmessagehandler
+ qlogging
diff --git a/tests/auto/corelib/global/qlogging/app/app.pro b/tests/auto/corelib/global/qlogging/app/app.pro
new file mode 100644
index 0000000000..a167cc45cd
--- /dev/null
+++ b/tests/auto/corelib/global/qlogging/app/app.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+
+TARGET = app
+QT = core
+
+CONFIG -= debug_and_release app_bundle
+CONFIG += debug console
+
+SOURCES += main.cpp
diff --git a/tests/auto/corelib/global/qlogging/app/main.cpp b/tests/auto/corelib/global/qlogging/app/main.cpp
new file mode 100644
index 0000000000..c26b29ea56
--- /dev/null
+++ b/tests/auto/corelib/global/qlogging/app/main.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+
+struct T {
+ T() { qDebug("static constructor"); }
+ ~T() { qDebug("static destructor"); }
+} t;
+
+int main(int, char **)
+{
+ qDebug("qDebug");
+ qWarning("qWarning");
+ qCritical("qCritical");
+ return 0;
+}
diff --git a/tests/auto/corelib/global/qlogging/qlogging.pro b/tests/auto/corelib/global/qlogging/qlogging.pro
new file mode 100644
index 0000000000..449b7dfa5e
--- /dev/null
+++ b/tests/auto/corelib/global/qlogging/qlogging.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ tst_qlogging.pro \
+ app \ No newline at end of file
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
new file mode 100644
index 0000000000..742a858961
--- /dev/null
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
@@ -0,0 +1,645 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdebug.h>
+#include <qglobal.h>
+#include <QtCore/QProcess>
+#include <QtTest/QtTest>
+
+class tst_qmessagehandler : public QObject
+{
+ Q_OBJECT
+private slots:
+ void cleanup();
+
+ void defaultHandler();
+ void installMessageHandler();
+ void installMsgHandler();
+ void installBothHandler();
+
+ void cleanupFuncinfo_data();
+ void cleanupFuncinfo();
+
+ void qMessagePattern();
+};
+
+static QtMsgType s_type;
+const char *s_file;
+int s_line;
+const char *s_function;
+static QString s_message;
+
+void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const char *msg)
+{
+ s_type = type;
+ s_file = context.file;
+ s_line = context.line;
+ s_function = context.function;
+ s_message = QString::fromLocal8Bit(msg);
+}
+
+void customMsgHandler(QtMsgType type, const char *msg)
+{
+ s_type = type;
+ s_file = 0;
+ s_line = 0;
+ s_function = 0;
+ s_message = QString::fromLocal8Bit(msg);
+}
+
+void tst_qmessagehandler::cleanup()
+{
+ qInstallMsgHandler(0);
+ qInstallMessageHandler(0);
+ s_type = QtFatalMsg;
+ s_file = 0;
+ s_line = 0;
+ s_function = 0;
+}
+
+void tst_qmessagehandler::defaultHandler()
+{
+ // check that the default works
+ QTest::ignoreMessage(QtDebugMsg, "defaultHandler");
+ qDebug("defaultHandler");
+}
+
+void tst_qmessagehandler::installMessageHandler()
+{
+ QMessageHandler oldHandler = qInstallMessageHandler(customMessageHandler);
+
+ qDebug("installMessageHandler"); int line = __LINE__;
+
+ QCOMPARE(s_type, QtDebugMsg);
+ QCOMPARE(s_message, QString::fromLocal8Bit("installMessageHandler"));
+ QCOMPARE(s_file, __FILE__);
+ QCOMPARE(s_function, Q_FUNC_INFO);
+ QCOMPARE(s_line, line);
+
+ QMessageHandler myHandler = qInstallMessageHandler(oldHandler);
+ QCOMPARE((void*)myHandler, (void*)customMessageHandler);
+}
+
+void tst_qmessagehandler::installMsgHandler()
+{
+ QtMsgHandler oldHandler = qInstallMsgHandler(customMsgHandler);
+
+ qDebug("installMsgHandler");
+
+ QCOMPARE(s_type, QtDebugMsg);
+ QCOMPARE(s_message, QString::fromLocal8Bit("installMsgHandler"));
+ QCOMPARE(s_file, (const char*)0);
+ QCOMPARE(s_function, (const char*)0);
+ QCOMPARE(s_line, 0);
+
+ QtMsgHandler myHandler = qInstallMsgHandler(oldHandler);
+ QCOMPARE((void*)myHandler, (void*)customMsgHandler);
+}
+
+void tst_qmessagehandler::installBothHandler()
+{
+ qInstallMessageHandler(customMessageHandler);
+ qInstallMsgHandler(customMsgHandler);
+
+ qDebug("installBothHandler"); int line = __LINE__;
+
+ QCOMPARE(s_type, QtDebugMsg);
+ QCOMPARE(s_message, QString::fromLocal8Bit("installBothHandler"));
+ QCOMPARE(s_file, __FILE__);
+ QCOMPARE(s_function, Q_FUNC_INFO);
+ QCOMPARE(s_line, line);
+}
+
+# define ADD(x) QTest::newRow(x) << Q_FUNC_INFO << x;
+
+class TestClass1
+{
+public:
+ enum Something { foo };
+
+ void func_void() { ADD("TestClass1::func_void"); }
+ int func_int() { ADD("TestClass1::func_int"); return 0; }
+ unsigned func_unsigned() { ADD("TestClass1::func_unsigned"); return 0; }
+ long func_long() { ADD("TestClass1::func_long"); return 0; }
+ long long func_ll() { ADD("TestClass1::func_ll"); return 0; }
+ unsigned long long func_ull() { ADD("TestClass1::func_ull"); return 0; }
+ char func_char() { ADD("TestClass1::func_char"); return 0; }
+ signed char func_schar() { ADD("TestClass1::func_schar"); return 0; }
+ unsigned char func_uchar() { ADD("TestClass1::func_uchar"); return 0; }
+ char *func_Pchar() { ADD("TestClass1::func_Pchar"); return 0; }
+ const char *func_KPchar() { ADD("TestClass1::func_KPchar"); return 0; }
+ const volatile char *func_VKPchar() { ADD("TestClass1::func_VKPchar"); return 0; }
+ const volatile unsigned long long * const volatile func_KVPKVull() { ADD("TestClass1::func_KVPKVull"); return 0; }
+ const void * const volatile *func_KPKVvoid() { ADD("TestClass1::func_KPKVvoid"); return 0; }
+
+ QList<int> func_ai() { ADD("TestClass1::func_ai"); return QList<int>(); }
+ QList<unsigned long long const volatile*> func_aptr() { ADD("TestClass1::func_aptr"); return QList<unsigned long long const volatile*>(); }
+
+ QList<Something> func_aenum() { ADD("TestClass1::func_aenum"); return QList<Something>(); }
+ QList<QList<const void *> > func_aaptr() { ADD("TestClass1::func_aaptr"); return QList<QList<const void *> >(); }
+
+ QMap<int, Something> func_ienummap() { ADD("TestClass1::func_ienummap"); return QMap<int, Something>(); }
+
+ template<typename T>
+ T* func_template1() { ADD("TestClass1::func_template1"); return 0; }
+ template<Something val>
+ long func_template2() { ADD("TestClass1::func_template2"); return long(val); }
+
+ typedef unsigned long long * ( *fptr)();
+ typedef unsigned long long * (TestClass1::* pmf)();
+ typedef fptr (TestClass1::* uglypmf)();
+ fptr func_fptr() { ADD("TestClass1::func_fptr"); return 0; }
+ pmf func_pmf() { ADD("TestClass1::func_pmf"); return 0; }
+ uglypmf func_uglypmf(uglypmf = 0) { ADD("TestClass1::func_uglypmf"); return 0; }
+ QMap<QString, uglypmf> func_uglypmf2() { ADD("TestClass1::func_uglypmf2"); return QMap<QString, uglypmf>(); }
+
+ void operator()() { ADD("TestClass1::operator()"); }
+ int operator<(int) { ADD("TestClass1::operator<"); return 0; }
+ int operator>(int) { ADD("TestClass1::operator>"); return 0; }
+ int operator<=(int) { ADD("TestClass1::operator<="); return 0; }
+ int operator>=(int) { ADD("TestClass1::operator>="); return 0; }
+ int operator=(int) { ADD("TestClass1::operator="); return 0; }
+ int operator+(int) { ADD("TestClass1::operator+"); return 0; }
+ int operator-(int) { ADD("TestClass1::operator-"); return 0; }
+ int operator*(int) { ADD("TestClass1::operator*"); return 0; }
+ int operator/(int) { ADD("TestClass1::operator/"); return 0; }
+ int operator%(int) { ADD("TestClass1::operator%"); return 0; }
+ int x;
+ int &operator++() { ADD("TestClass1::operator++"); return x; }
+ int operator++(int) { ADD("TestClass1::operator++"); return 0; }
+ int &operator--() { ADD("TestClass1::operator--"); return x; }
+ int operator--(int) { ADD("TestClass1::operator--"); return 0; }
+
+public:
+ TestClass1()
+ {
+ // instantiate
+ func_void();
+ func_int();
+ func_unsigned();
+ func_long();
+ func_ll();
+ func_ull();
+ func_char();
+ func_schar();
+ func_uchar();
+ func_Pchar();
+ func_KPchar();
+ func_VKPchar();
+ func_KVPKVull();
+ func_KPKVvoid();
+ func_ai();
+ func_aptr();
+ func_aenum();
+ func_aaptr();
+ func_ienummap();
+ func_template1<TestClass1>();
+ func_template2<foo>();
+ func_fptr();
+ func_pmf();
+ func_uglypmf();
+ func_uglypmf2();
+ operator()();
+ operator<(0);
+ operator>(0);
+ operator<=(0);
+ operator>=(0);
+ operator=(0);
+ operator+(0);
+ operator-(0);
+ operator*(0);
+ operator/(0);
+ operator%(0);
+ operator++();
+ operator++(0);
+ operator--();
+ operator--(0);
+ }
+};
+
+template<typename T> class TestClass2
+{
+ long func_long() { ADD("TestClass2::func_long"); return 0; }
+ template<typename S>
+ T* func_template1() { ADD("TestClass2::func_template1"); return 0; }
+ template<TestClass1::Something val>
+ long func_template2() { ADD("TestClass2::func_template2"); return long(val); }
+public:
+ TestClass2()
+ {
+ func_long();
+ func_template1<TestClass2>();
+ func_template2<TestClass1::foo>();
+ }
+};
+
+template<typename T, TestClass1::Something v> class TestClass3
+{
+ long func_long() { ADD("TestClass3::func_long"); return 0; }
+ template<typename S>
+ S* func_template1() { ADD("TestClass3::func_template1"); return 0; }
+ template<TestClass1::Something val>
+ long func_template2() { ADD("TestClass3::func_template2"); return long(val); }
+public:
+ struct Foo { TestClass3 foo; };
+ TestClass3()
+ {
+ func_long();
+ func_template1<TestClass2<T> >();
+ func_template2<TestClass1::foo>();
+ }
+};
+
+class TestClass4
+{
+ TestClass1 c1;
+
+ TestClass2<std::map<long, const void *> > func2()
+ { ADD("TestClass4::func2"); return TestClass2<std::map<long, const void *> >(); }
+ TestClass3<std::map<std::list<int>, const void *>, TestClass1::foo>::Foo func3()
+ { ADD("TestClass4::func3"); return TestClass3<std::map<std::list<int>, const void *>, TestClass1::foo>::Foo(); }
+public:
+ TestClass4()
+ {
+ func2();
+ func3();
+ ADD("TestClass4::TestClass4");
+ }
+ ~TestClass4()
+ {
+ ADD("TestClass4::~TestClass4");
+ }
+};
+
+
+void tst_qmessagehandler::cleanupFuncinfo_data()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("Requires -developer-build");
+#endif
+ QTest::addColumn<QString>("funcinfo");
+ QTest::addColumn<QString>("expected");
+
+ TestClass4 c4;
+
+ QTest::newRow("msvc_01")
+ << "void __thiscall TestClass1::func_void(void)"
+ << "TestClass1::func_void";
+ QTest::newRow("gcc_01")
+ << "void TestClass1::func_void()"
+ << "TestClass1::func_void";
+
+ QTest::newRow("msvc_02")
+ << "int __thiscall TestClass1::func_int(void)"
+ << "TestClass1::func_int";
+ QTest::newRow("gcc_02")
+ << "int TestClass1::func_int()"
+ << "TestClass1::func_int";
+
+ QTest::newRow("msvc_03")
+ << "unsigned int __thiscall TestClass1::func_unsigned(void)"
+ << "TestClass1::func_unsigned";
+ QTest::newRow("gcc_03")
+ << "unsigned int TestClass1::func_unsigned()"
+ << "TestClass1::func_unsigned";
+
+ QTest::newRow("msvc_04")
+ << "long __thiscall TestClass1::func_long(void)"
+ << "TestClass1::func_long";
+ QTest::newRow("gcc_04")
+ << "long int TestClass1::func_long()"
+ << "TestClass1::func_long";
+
+ QTest::newRow("msvc_05")
+ << "__int64 __thiscall TestClass1::func_ll(void)"
+ << "TestClass1::func_ll";
+ QTest::newRow("gcc_05")
+ << "long long int TestClass1::func_ll()"
+ << "TestClass1::func_ll";
+
+ QTest::newRow("msvc_06")
+ << "unsigned __int64 __thiscall TestClass1::func_ull(void)"
+ << "TestClass1::func_ull";
+ QTest::newRow("gcc_06")
+ << "long long unsigned int TestClass1::func_ull()"
+ << "TestClass1::func_ull";
+
+ QTest::newRow("msvc_07")
+ << "char __thiscall TestClass1::func_char(void)"
+ << "TestClass1::func_char";
+ QTest::newRow("gcc_07")
+ << "char TestClass1::func_char()"
+ << "TestClass1::func_char";
+
+ QTest::newRow("msvc_08")
+ << "signed char __thiscall TestClass1::func_schar(void)"
+ << "TestClass1::func_schar";
+ QTest::newRow("gcc_08")
+ << "signed char TestClass1::func_schar()"
+ << "TestClass1::func_schar";
+
+ QTest::newRow("msvc_09")
+ << "unsigned char __thiscall TestClass1::func_uchar(void)"
+ << "TestClass1::func_uchar";
+ QTest::newRow("gcc_09")
+ << "unsigned char TestClass1::func_uchar()"
+ << "TestClass1::func_uchar";
+
+ QTest::newRow("msvc_10")
+ << "char *__thiscall TestClass1::func_Pchar(void)"
+ << "TestClass1::func_Pchar";
+ QTest::newRow("gcc_10")
+ << "char* TestClass1::func_Pchar()"
+ << "TestClass1::func_Pchar";
+
+ QTest::newRow("msvc_11")
+ << "const char *__thiscall TestClass1::func_KPchar(void)"
+ << "TestClass1::func_KPchar";
+ QTest::newRow("gcc_11")
+ << "const char* TestClass1::func_KPchar()"
+ << "TestClass1::func_KPchar";
+
+ QTest::newRow("msvc_12")
+ << "volatile const char *__thiscall TestClass1::func_VKPchar(void)"
+ << "TestClass1::func_VKPchar";
+ QTest::newRow("gcc_12")
+ << "const volatile char* TestClass1::func_VKPchar()"
+ << "TestClass1::func_VKPchar";
+
+ QTest::newRow("msvc_13")
+ << "volatile const unsigned __int64 *volatile const __thiscall TestClass1::func_KVPKVull(void)"
+ << "TestClass1::func_KVPKVull";
+ QTest::newRow("gcc_13")
+ << "const volatile long long unsigned int* const volatile TestClass1::func_KVPKVull()"
+ << "TestClass1::func_KVPKVull";
+
+ QTest::newRow("msvc_14")
+ << "const void *volatile const *__thiscall TestClass1::func_KPKVvoid(void)"
+ << "TestClass1::func_KPKVvoid";
+ QTest::newRow("gcc_14")
+ << "const void* const volatile* TestClass1::func_KPKVvoid()"
+ << "TestClass1::func_KPKVvoid";
+
+ QTest::newRow("msvc_15")
+ << "class QList<int> __thiscall TestClass1::func_ai(void)"
+ << "TestClass1::func_ai";
+ QTest::newRow("gcc_15")
+ << "QList<int> TestClass1::func_ai()"
+ << "TestClass1::func_ai";
+
+ QTest::newRow("msvc_16")
+ << "class QList<unsigned __int64 const volatile *> __thiscall TestClass1::func_aptr(void)"
+ << "TestClass1::func_aptr";
+ QTest::newRow("gcc_16")
+ << "QList<const volatile long long unsigned int*> TestClass1::func_aptr()"
+ << "TestClass1::func_aptr";
+
+ QTest::newRow("msvc_17")
+ << "class QList<enum TestClass1::Something> __thiscall TestClass1::func_aenum(void)"
+ << "TestClass1::func_aenum";
+ QTest::newRow("gcc_17")
+ << "QList<TestClass1::Something> TestClass1::func_aenum()"
+ << "TestClass1::func_aenum";
+
+ QTest::newRow("msvc_18")
+ << "class QList<class QList<void const *> > __thiscall TestClass1::func_aaptr(void)"
+ << "TestClass1::func_aaptr";
+ QTest::newRow("gcc_18")
+ << "QList<QList<const void*> > TestClass1::func_aaptr()"
+ << "TestClass1::func_aaptr";
+
+ QTest::newRow("msvc_19")
+ << "class QMap<int,enum TestClass1::Something> __thiscall TestClass1::func_ienummap(void)"
+ << "TestClass1::func_ienummap";
+ QTest::newRow("gcc_19")
+ << "QMap<int, TestClass1::Something> TestClass1::func_ienummap()"
+ << "TestClass1::func_ienummap";
+
+ QTest::newRow("msvc_20")
+ << "class TestClass1 *__thiscall TestClass1::func_template1<class TestClass1>(void)"
+ << "TestClass1::func_template1";
+ QTest::newRow("gcc_20")
+ << "T* TestClass1::func_template1() [with T = TestClass1]"
+ << "TestClass1::func_template1";
+
+ QTest::newRow("msvc_21")
+ << "long __thiscall TestClass1::func_template2<foo>(void)"
+ << "TestClass1::func_template2";
+ QTest::newRow("gcc_21")
+ << "long int TestClass1::func_template2() [with TestClass1::Something val = foo]"
+ << "TestClass1::func_template2";
+
+ QTest::newRow("msvc_22")
+ << "unsigned __int64 *(__cdecl *__thiscall TestClass1::func_fptr(void))(void)"
+ << "TestClass1::func_fptr";
+ QTest::newRow("gcc_22")
+ << "long long unsigned int* (* TestClass1::func_fptr())()"
+ << "TestClass1::func_fptr";
+
+ QTest::newRow("msvc_23")
+ << "unsigned __int64 *(__thiscall TestClass1::* __thiscall TestClass1::func_pmf(void))(void)"
+ << "TestClass1::func_pmf";
+ QTest::newRow("gcc_23")
+ << "long long unsigned int* (TestClass1::* TestClass1::func_pmf())()"
+ << "TestClass1::func_pmf";
+
+ QTest::newRow("msvc_24")
+ << "unsigned __int64 *(__cdecl *(__thiscall TestClass1::* __thiscall TestClass1::func_uglypmf(unsigned __int64 *(__cdecl *(__thiscall TestClass1::* )(void))(void)))(void))(void)"
+ << "TestClass1::func_uglypmf";
+ QTest::newRow("gcc_24")
+ << "long long unsigned int* (* (TestClass1::* TestClass1::func_uglypmf(long long unsigned int* (* (TestClass1::*)())()))())()"
+ << "TestClass1::func_uglypmf";
+
+ QTest::newRow("msvc_25")
+ << "class QMap<class QString,unsigned __int64 * (__cdecl*(__thiscall TestClass1::*)(void))(void)> __thiscall TestClass1::func_uglypmf2(void)"
+ << "TestClass1::func_uglypmf2";
+ QTest::newRow("gcc_25")
+ << "QMap<QString, long long unsigned int* (* (TestClass1::*)())()> TestClass1::func_uglypmf2()"
+ << "TestClass1::func_uglypmf2";
+
+ QTest::newRow("msvc_26")
+ << "class TestClass2<class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > > __thiscall TestClass4::func2(void)"
+ << "TestClass4::func2";
+ QTest::newRow("gcc_26")
+ << "TestClass2<std::map<long int, const void*, std::less<long int>, std::allocator<std::pair<const long int, const void*> > > > TestClass4::func2()"
+ << "TestClass4::func2";
+
+ QTest::newRow("msvc_27")
+ << "long __thiscall TestClass2<class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > >::func_long(void)"
+ << "TestClass2::func_long";
+ QTest::newRow("gcc_27")
+ << "long int TestClass2<T>::func_long() [with T = std::map<long int, const void*, std::less<long int>, std::allocator<std::pair<const long int, const void*> > >]"
+ << "TestClass2::func_long";
+
+ QTest::newRow("msvc_28")
+ << "class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > *__thiscall TestClass2<class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > >::func_template1<class TestClass2<class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > >>(void)"
+ << "TestClass2::func_template1";
+ QTest::newRow("gcc_21")
+ << "T* TestClass2<T>::func_template1() [with S = TestClass2<std::map<long int, const void*, std::less<long int>, std::allocator<std::pair<const long int, const void*> > > >, T = std::map<long int, const void*, std::less<long int>, std::allocator<std::pair<const long int, const void*> > >]"
+ << "TestClass2::func_template1";
+
+ QTest::newRow("msvc_29")
+ << "long __thiscall TestClass2<class std::map<long,void const *,struct std::less<long>,class std::allocator<struct std::pair<long const ,void const *> > > >::func_template2<foo>(void)"
+ << "TestClass2::func_template2";
+ QTest::newRow("gcc_29")
+ << "long int TestClass2<T>::func_template2() [with TestClass1::Something val = foo, T = std::map<long int, const void*, std::less<long int>, std::allocator<std::pair<const long int, const void*> > >]"
+ << "TestClass2::func_template2";
+
+ QTest::newRow("msvc_30")
+ << "struct TestClass3<class std::map<class std::list<int,class std::allocator<int> >,void const *,struct std::less<class std::list<int,class std::allocator<int> > >,class std::allocator<struct std::pair<class std::list<int,class std::allocator<int> > const ,void const *> > >,0>::Foo __thiscall TestClass4::func3(void)"
+ << "TestClass4::func3";
+ QTest::newRow("gcc_30")
+ << "TestClass3<std::map<std::list<int, std::allocator<int> >, const void*, std::less<std::list<int, std::allocator<int> > >, std::allocator<std::pair<const std::list<int, std::allocator<int> >, const void*> > >, foo>::Foo TestClass4::func3()"
+ << "TestClass4::func3";
+
+ QTest::newRow("msvc_31")
+ << "long __thiscall TestClass3<class std::map<class std::list<int,class std::allocator<int> >,void const *,struct std::less<class std::list<int,class std::allocator<int> > >,class std::allocator<struct std::pair<class std::list<int,class std::allocator<int> > const ,void const *> > >,0>::func_long(void)"
+ << "TestClass3::func_long";
+ QTest::newRow("gcc_31")
+ << "long int TestClass3<T, v>::func_long() [with T = std::map<std::list<int, std::allocator<int> >, const void*, std::less<std::list<int, std::allocator<int> > >, std::allocator<std::pair<const std::list<int, std::allocator<int> >, const void*> > >, TestClass1::Something v = foo]"
+ << "TestClass3::func_long";
+
+ QTest::newRow("msvc_32")
+ << "class TestClass2<class std::map<class std::list<int,class std::allocator<int> >,void const *,struct std::less<class std::list<int,class std::allocator<int> > >,class std::allocator<struct std::pair<class std::list<int,class std::allocator<int> > const ,void const *> > > > *__thiscall TestClass3<class std::map<class std::list<int,class std::allocator<int> >,void const *,struct std::less<class std::list<int,class std::allocator<int> > >,class std::allocator<struct std::pair<class std::list<int,class std::allocator<int> > const ,void const *> > >,0>::func_template1<class TestClass2<class std::map<class std::list<int,class std::allocator<int> >,void const *,struct std::less<class std::list<int,class std::allocator<int> > >,class std::allocator<struct std::pair<class std::list<int,class std::allocator<int> > const ,void const *> > > >>(void)"
+ << "TestClass3::func_template1";
+ QTest::newRow("gcc_32")
+ << "S* TestClass3<T, v>::func_template1() [with S = TestClass2<std::map<std::list<int, std::allocator<int> >, const void*, std::less<std::list<int, std::allocator<int> > >, std::allocator<std::pair<const std::list<int, std::allocator<int> >, const void*> > > >, T = std::map<std::list<int, std::allocator<int> >, const void*, std::less<std::list<int, std::allocator<int> > >, std::allocator<std::pair<const std::list<int, std::allocator<int> >, const void*> > >, TestClass1::Something v = foo]"
+ << "TestClass3::func_template1";
+
+ QTest::newRow("msvc_33")
+ << "long __thiscall TestClass3<class std::map<class std::list<int,class std::allocator<int> >,void const *,struct std::less<class std::list<int,class std::allocator<int> > >,class std::allocator<struct std::pair<class std::list<int,class std::allocator<int> > const ,void const *> > >,0>::func_template2<foo>(void)"
+ << "TestClass3::func_template2";
+ QTest::newRow("gcc_33")
+ << "long int TestClass3<T, v>::func_template2() [with TestClass1::Something val = foo, T = std::map<std::list<int, std::allocator<int> >, const void*, std::less<std::list<int, std::allocator<int> > >, std::allocator<std::pair<const std::list<int, std::allocator<int> >, const void*> > >, TestClass1::Something v = foo]"
+ << "TestClass3::func_template2";
+
+ QTest::newRow("msvc_34")
+ << "__thiscall TestClass4::TestClass4(void)"
+ << "TestClass4::TestClass4";
+ QTest::newRow("gcc_34")
+ << "TestClass4::TestClass4()"
+ << "TestClass4::TestClass4";
+
+ QTest::newRow("msvc_35")
+ << "__thiscall TestClass4::~TestClass4(void)"
+ << "TestClass4::~TestClass4";
+ QTest::newRow("gcc_35")
+ << "TestClass4::~TestClass4()"
+ << "TestClass4::~TestClass4";
+
+ QTest::newRow("gcc_36")
+ << "void TestClass1::operator()()"
+ << "TestClass1::operator()";
+
+ QTest::newRow("gcc_37")
+ << "long int TestClass1::func_template2() [with TestClass1::Something val = (TestClass1::Something)0u]"
+ << "TestClass1::func_template2";
+
+ QTest::newRow("gcc_38")
+ << "int TestClass1::operator<(int)"
+ << "TestClass1::operator<";
+
+ QTest::newRow("gcc_39")
+ << "int TestClass1::operator>(int)"
+ << "TestClass1::operator>";}
+
+#ifdef QT_BUILD_INTERNAL
+QT_BEGIN_NAMESPACE
+extern QByteArray qCleanupFuncinfo(QByteArray);
+QT_END_NAMESPACE
+#endif
+
+void tst_qmessagehandler::cleanupFuncinfo()
+{
+#ifdef QT_BUILD_INTERNAL
+ QFETCH(QString, funcinfo);
+
+ QByteArray result = qCleanupFuncinfo(funcinfo.toLatin1());
+ QTEST(QString::fromLatin1(result), "expected");
+#endif
+}
+
+void tst_qmessagehandler::qMessagePattern()
+{
+ QProcess process;
+
+ QStringList environment = QProcess::systemEnvironment();
+ // %{file} is tricky because of shadow builds
+ environment.prepend("QT_MESSAGE_PATTERN=\"%{type} %{line} %{function} %{message}\"");
+ process.setEnvironment(environment);
+#ifdef Q_OS_WIN
+ process.start("app/app.exe");
+#else
+ process.start("app/app");
+#endif
+ process.waitForFinished();
+
+ QByteArray output = process.readAllStandardError();
+// qDebug() << output;
+ QVERIFY(!output.isEmpty());
+
+ QVERIFY(output.contains("debug 45 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 51 main qDebug"));
+ QVERIFY(output.contains("warning 52 main qWarning"));
+ QVERIFY(output.contains("critical 53 main qCritical"));
+
+ environment = QProcess::systemEnvironment();
+ environment.prepend("QT_MESSAGE_PATTERN=\"PREFIX: %{unknown} %{message}\"");
+ process.setEnvironment(environment);
+#ifdef Q_OS_WIN
+ process.start("app/app.exe");
+#else
+ process.start("app/app");
+#endif
+ process.waitForFinished();
+
+ output = process.readAllStandardError();
+// qDebug() << output;
+ QVERIFY(!output.isEmpty());
+
+ QVERIFY(output.contains("QT_MESSAGE_PATTERN: Unknown placeholder %{unknown}"));
+ QVERIFY(output.contains("PREFIX: qDebug"));
+}
+
+QTEST_MAIN(tst_qmessagehandler)
+#include "tst_qlogging.moc"
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.pro b/tests/auto/corelib/global/qlogging/tst_qlogging.pro
new file mode 100644
index 0000000000..60377e0fdc
--- /dev/null
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qlogging
+QT = core testlib
+SOURCES = tst_qlogging.cpp
diff --git a/tests/auto/corelib/global/qmessagehandler/qmessagehandler.pro b/tests/auto/corelib/global/qmessagehandler/qmessagehandler.pro
deleted file mode 100644
index 8bdba4bfc4..0000000000
--- a/tests/auto/corelib/global/qmessagehandler/qmessagehandler.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-CONFIG += testcase parallel_test
-TARGET = tst_qmessagehandler
-QT = core testlib
-SOURCES = tst_qmessagehandler.cpp
diff --git a/tests/auto/corelib/global/qmessagehandler/tst_qmessagehandler.cpp b/tests/auto/corelib/global/qmessagehandler/tst_qmessagehandler.cpp
deleted file mode 100644
index 39bd0986a5..0000000000
--- a/tests/auto/corelib/global/qmessagehandler/tst_qmessagehandler.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qdebug.h>
-#include <QtTest/QtTest>
-
-#include <qglobal.h>
-
-class tst_qmessagehandler : public QObject
-{
- Q_OBJECT
-private slots:
- void cleanup();
-
- void defaultHandler();
- void installMessageHandler();
- void installMsgHandler();
- void installBothHandler();
-};
-
-static QtMsgType s_type;
-const char *s_file;
-int s_line;
-const char *s_function;
-static QString s_message;
-
-void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const char *msg)
-{
- s_type = type;
- s_file = context.file;
- s_line = context.line;
- s_function = context.function;
- s_message = QString::fromLocal8Bit(msg);
-}
-
-void customMsgHandler(QtMsgType type, const char *msg)
-{
- s_type = type;
- s_file = 0;
- s_line = 0;
- s_function = 0;
- s_message = QString::fromLocal8Bit(msg);
-}
-
-void tst_qmessagehandler::cleanup()
-{
- qInstallMsgHandler(0);
- qInstallMessageHandler(0);
- s_type = QtFatalMsg;
- s_file = 0;
- s_line = 0;
- s_function = 0;
-}
-
-void tst_qmessagehandler::defaultHandler()
-{
- // check that the default works
- QTest::ignoreMessage(QtDebugMsg, "defaultHandler");
- qDebug("defaultHandler");
-}
-
-void tst_qmessagehandler::installMessageHandler()
-{
- QMessageHandler oldHandler = qInstallMessageHandler(customMessageHandler);
-
- qDebug("installMessageHandler"); int line = __LINE__;
-
- QCOMPARE(s_type, QtDebugMsg);
- QCOMPARE(s_message, QString::fromLocal8Bit("installMessageHandler"));
- QCOMPARE(s_file, __FILE__);
- QCOMPARE(s_function, Q_FUNC_INFO);
- QCOMPARE(s_line, line);
-
- QMessageHandler myHandler = qInstallMessageHandler(oldHandler);
- QCOMPARE((void*)myHandler, (void*)customMessageHandler);
-}
-
-void tst_qmessagehandler::installMsgHandler()
-{
- QtMsgHandler oldHandler = qInstallMsgHandler(customMsgHandler);
-
- qDebug("installMsgHandler");
-
- QCOMPARE(s_type, QtDebugMsg);
- QCOMPARE(s_message, QString::fromLocal8Bit("installMsgHandler"));
- QCOMPARE(s_file, (const char*)0);
- QCOMPARE(s_function, (const char*)0);
- QCOMPARE(s_line, 0);
-
- QtMsgHandler myHandler = qInstallMsgHandler(oldHandler);
- QCOMPARE((void*)myHandler, (void*)customMsgHandler);
-}
-
-void tst_qmessagehandler::installBothHandler()
-{
- qInstallMessageHandler(customMessageHandler);
- qInstallMsgHandler(customMsgHandler);
-
- qDebug("installBothHandler"); int line = __LINE__;
-
- QCOMPARE(s_type, QtDebugMsg);
- QCOMPARE(s_message, QString::fromLocal8Bit("installBothHandler"));
- QCOMPARE(s_file, __FILE__);
- QCOMPARE(s_function, Q_FUNC_INFO);
- QCOMPARE(s_line, line);
-}
-
-QTEST_MAIN(tst_qmessagehandler)
-#include "tst_qmessagehandler.moc"
diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro
index d39d9b45cc..f68e3c0e54 100644
--- a/tools/configure/configure.pro
+++ b/tools/configure/configure.pro
@@ -46,6 +46,7 @@ HEADERS = configureapp.h environment.h tools.h\
$$QT_SOURCE_TREE/src/corelib/codecs/qtextcodec.h \
$$QT_SOURCE_TREE/src/corelib/global/qglobal.h \
$$QT_SOURCE_TREE/src/corelib/global/qnumeric.h \
+ $$QT_SOURCE_TREE/src/corelib/global/qlogging.h \
$$QT_SOURCE_TREE/src/corelib/io/qbuffer.h \
$$QT_SOURCE_TREE/src/corelib/io/qdatastream.h \
$$QT_SOURCE_TREE/src/corelib/io/qdir.h \
@@ -89,6 +90,7 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \
$$QT_SOURCE_TREE/src/corelib/codecs/qtextcodec.cpp \
$$QT_SOURCE_TREE/src/corelib/global/qglobal.cpp \
$$QT_SOURCE_TREE/src/corelib/global/qnumeric.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qlogging.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qbuffer.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qdatastream.cpp \
$$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \