Import qlogger framework
Merge most parts of the qlogger framework from git://gitorious.org/qtplayground/qlogger.git The categorized logging feature is a replacement for qDebug, qWarning and friends. With logging statements in an app/library, a developer can turn on the statements they care about and turn off the ones they don't. Most work for this was done by Wolfgang Beck and Lincoln Ramsay. Task-number: QTBUG-25694 Change-Id: Ib0cdfbbf3694f86ad9ec553b2ea36f09a477cded Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
99f9bf9af6
commit
3efca77e35
113
src/corelib/doc/snippets/qloggingcategory/main.cpp
Normal file
113
src/corelib/doc/snippets/qloggingcategory/main.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
|
||||
** of its contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
//![1]
|
||||
// in a header
|
||||
Q_DECLARE_LOGGING_CATEGORY(QT_DRIVER_USB)
|
||||
|
||||
// in one source file
|
||||
Q_LOGGING_CATEGORY(QT_DRIVER_USB, "qt.driver.usb")
|
||||
//![1]
|
||||
|
||||
|
||||
// Completely made up example, inspired by en.wikipedia.org/wiki/USB :)
|
||||
struct UsbEntry {
|
||||
int id;
|
||||
int classtype;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug &dbg, const UsbEntry &entry)
|
||||
{
|
||||
dbg.nospace() << "" << entry.id << " (" << entry.classtype << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QList<UsbEntry> usbEntries() {
|
||||
QList<UsbEntry> entries;
|
||||
return entries;
|
||||
}
|
||||
|
||||
void main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
//![2]
|
||||
// don't run the expensive code if the string won't print
|
||||
if (QT_DRIVER_USB().isEnabled<QtDebugMsg>()) {
|
||||
QStringList items;
|
||||
foreach (const UsbEntry &entry, usbEntries())
|
||||
items << QString("%1 (%2)").arg(entry.id, entry.classtype);
|
||||
qCDebug(QT_DRIVER_USB) << "devices: " << items;
|
||||
}
|
||||
//![2]
|
||||
|
||||
//![3]
|
||||
// usbEntries() will only be called if QT_DRIVER_USB category is enabled
|
||||
qCDebug(QT_DRIVER_USB) << "devices: " << usbEntries();
|
||||
//![3]
|
||||
|
||||
{
|
||||
//![10]
|
||||
QLoggingCategory category("qt.driver.usb");
|
||||
qCDebug(category) << "a debug message";
|
||||
//![10]
|
||||
}
|
||||
|
||||
{
|
||||
//![11]
|
||||
QLoggingCategory category("qt.driver.usb");
|
||||
qCWarning(category) << "a warning message";
|
||||
//![11]
|
||||
}
|
||||
|
||||
{
|
||||
//![12]
|
||||
QLoggingCategory category("qt.driver.usb");
|
||||
qCCritical(category) << "a critical message";
|
||||
//![12]
|
||||
}
|
||||
}
|
||||
|
||||
//![20]
|
||||
void myCategoryFilter(QLoggingCategory *);
|
||||
//![20]
|
@ -49,6 +49,8 @@
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#include "qcoreapplication.h"
|
||||
#include "qthread.h"
|
||||
#include "qloggingcategory.h"
|
||||
#include "private/qloggingregistry_p.h"
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
#include <qt_windows.h>
|
||||
@ -920,6 +922,14 @@ static void qDefaultMsgHandler(QtMsgType type, const char *buf)
|
||||
|
||||
static void qt_message_print(QtMsgType msgType, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
// qDebug, qWarning, ... macros do not check whether category is enabled
|
||||
if (!context.category || (strcmp(context.category, "default") == 0)) {
|
||||
if (!QLoggingCategory::defaultCategory().isEnabled(msgType))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!msgHandler)
|
||||
msgHandler = qDefaultMsgHandler;
|
||||
if (!messageHandler)
|
||||
@ -1151,6 +1161,7 @@ void qSetMessagePattern(const QString &pattern)
|
||||
qMessagePattern()->setPattern(pattern);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Copies context information from \a logContext into this QMessageLogContext
|
||||
\internal
|
||||
|
@ -49,7 +49,10 @@ HEADERS += \
|
||||
io/qfilesystemmetadata_p.h \
|
||||
io/qfilesystemiterator_p.h \
|
||||
io/qfileselector.h \
|
||||
io/qfileselector_p.h
|
||||
io/qfileselector_p.h \
|
||||
io/qloggingcategory.h \
|
||||
io/qloggingcategory_p.h \
|
||||
io/qloggingregistry_p.h
|
||||
|
||||
SOURCES += \
|
||||
io/qabstractfileengine.cpp \
|
||||
@ -86,7 +89,9 @@ SOURCES += \
|
||||
io/qfilesystemwatcher_polling.cpp \
|
||||
io/qfilesystementry.cpp \
|
||||
io/qfilesystemengine.cpp \
|
||||
io/qfileselector.cpp
|
||||
io/qfileselector.cpp \
|
||||
io/qloggingcategory.cpp \
|
||||
io/qloggingregistry.cpp
|
||||
|
||||
win32 {
|
||||
SOURCES += io/qsettings_win.cpp
|
||||
|
352
src/corelib/io/qloggingcategory.cpp
Normal file
352
src/corelib/io/qloggingcategory.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qloggingcategory.h"
|
||||
#include "qloggingcategory_p.h"
|
||||
#include "qloggingregistry_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
const char qtDefaultCategoryName[] = "default";
|
||||
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
|
||||
(qtDefaultCategoryName))
|
||||
|
||||
/*!
|
||||
\class QLoggingCategory
|
||||
\inmodule QtCore
|
||||
\since 5.2
|
||||
|
||||
\brief A category, or 'area' in the logging infrastructure.
|
||||
|
||||
QLoggingCategory represents a certain logging category - identified
|
||||
by a string - at runtime. Whether a category should be actually logged or
|
||||
not can be checked with the \l isEnabled() methods.
|
||||
|
||||
\section1 Creating category objects
|
||||
|
||||
Qt provides the \l Q_LOGGING_CATEGORY(), Q_DECLARE_LOGGING_CATEGORY() macros
|
||||
to conveniently create static QLoggingCategory objects on the heap:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 1
|
||||
|
||||
\section1 Checking category configuration
|
||||
|
||||
QLoggingCategory provides two isEnabled methods, a template one and a
|
||||
non-template one, for checking whether the current category is enabled.
|
||||
The template version checks for the most common case that no special rules
|
||||
are applied in inline code, and should be preferred:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 2
|
||||
|
||||
Note that qCDebug() prevents arguments from being evaluated
|
||||
if the string won't print, so calling isEnabled explicitly is not needed:
|
||||
\l isEnabled().
|
||||
|
||||
\snippet qloggingcategory/main.cpp 3
|
||||
|
||||
\section1 Default configuration
|
||||
|
||||
In the default configuration \l isEnabled() will return true for all
|
||||
\l QtMsgType types except QtDebugMsg: QtDebugMsg is only active by default
|
||||
for the \c "default" category.
|
||||
|
||||
\section1 Changing configuration
|
||||
|
||||
The default configuration can be changed by calling \l setEnabled(). However,
|
||||
this only affects the current category object, not e.g. another object for the
|
||||
same category name. Use either \l setFilterRules() or \l installFilter() to
|
||||
configure categories globally.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a QLoggingCategory object with the provided \a category name.
|
||||
The object becomes the local identifier for the category.
|
||||
|
||||
If \a category is \c{0}, the category name is changed to \c{"default"}.
|
||||
*/
|
||||
QLoggingCategory::QLoggingCategory(const char *category)
|
||||
: name(0),
|
||||
enabledDebug(false),
|
||||
enabledWarning(true),
|
||||
enabledCritical(true)
|
||||
{
|
||||
bool isDefaultCategory
|
||||
= (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0);
|
||||
|
||||
if (isDefaultCategory) {
|
||||
// normalize default category names, so that we can just do
|
||||
// pointer comparison in QLoggingRegistry::updateCategory
|
||||
name = qtDefaultCategoryName;
|
||||
enabledDebug = true;
|
||||
} else {
|
||||
name = category;
|
||||
}
|
||||
|
||||
if (QLoggingRegistry *reg = QLoggingRegistry::instance())
|
||||
reg->registerCategory(this);}
|
||||
|
||||
/*!
|
||||
Destructs a QLoggingCategory object
|
||||
*/
|
||||
QLoggingCategory::~QLoggingCategory()
|
||||
{
|
||||
if (QLoggingRegistry *reg = QLoggingRegistry::instance())
|
||||
reg->unregisterCategory(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn const char *QLoggingCategory::categoryName() const
|
||||
|
||||
Returns the name of the category.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QLoggingCategory::isEnabled() const
|
||||
|
||||
Returns true if a message of the template \c QtMsgType argument should be
|
||||
shown. Returns false otherwise.
|
||||
|
||||
\note The qCDebug, qCWarning, qCCritical macros already do this check before
|
||||
executing any code. However, calling this method may be useful to avoid
|
||||
expensive generation of data that is only used for debug output.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns true if a message of type \a msgtype for the category should be
|
||||
shown. Returns false otherwise.
|
||||
|
||||
\note The templated, inline version of this method, \l isEnabled(), is
|
||||
optimized for the common case that no configuration is set, and should
|
||||
generally be preferred.
|
||||
*/
|
||||
bool QLoggingCategory::isEnabled(QtMsgType msgtype) const
|
||||
{
|
||||
switch (msgtype) {
|
||||
case QtDebugMsg: return enabledDebug;
|
||||
case QtWarningMsg: return enabledWarning;
|
||||
case QtCriticalMsg: return enabledCritical;
|
||||
case QtFatalMsg: return true;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Changes the type \a type for the category to \a enable.
|
||||
|
||||
Changes only affect the current QLoggingCategory object, and won't
|
||||
change e.g. the settings of another objects for the same category name.
|
||||
|
||||
\note QtFatalMsg cannot be changed. It will always return true.
|
||||
*/
|
||||
void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
|
||||
{
|
||||
switch (type) {
|
||||
case QtDebugMsg: enabledDebug = enable; break;
|
||||
case QtWarningMsg: enabledWarning = enable; break;
|
||||
case QtCriticalMsg: enabledCritical = enable; break;
|
||||
case QtFatalMsg:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QLoggingCategory &QLoggingCategory::operator()()
|
||||
|
||||
Returns the object itself. This allows both a QLoggingCategory variable, and
|
||||
a factory method returning a QLoggingCategory, to be used in qCDebug(),
|
||||
qCWarning(), qCCritial() macros.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns the category "default" that is used e.g. by qDebug(), qWarning(),
|
||||
qCritical(), qFatal().
|
||||
*/
|
||||
QLoggingCategory &QLoggingCategory::defaultCategory()
|
||||
{
|
||||
return *qtDefaultCategory();
|
||||
}
|
||||
|
||||
/*!
|
||||
\typedef QLoggingCategory::CategoryFilter
|
||||
|
||||
This is a typedef for a pointer to a function with the following
|
||||
signature:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 20
|
||||
|
||||
A function with this signature can be installed with \l installFilter().
|
||||
*/
|
||||
|
||||
/*!
|
||||
Installs a function \a filter that is used to determine which categories
|
||||
and message types should be enabled. Returns a pointer to the previous
|
||||
installed filter.
|
||||
|
||||
Every QLoggingCategory object created is passed to the filter, and the
|
||||
filter is free to change the respective category configuration with
|
||||
\l setEnabled().
|
||||
|
||||
An alternative way of configuring the default filter is via
|
||||
\l setFilterRules().
|
||||
*/
|
||||
QLoggingCategory::CategoryFilter
|
||||
QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter)
|
||||
{
|
||||
return QLoggingRegistry::instance()->installFilter(filter);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Configures which categories and message types should be enabled through a
|
||||
a set of \a rules.
|
||||
|
||||
Each line in \a rules must have the format
|
||||
|
||||
\code
|
||||
<category>[.<type>] = true|false
|
||||
\endcode
|
||||
|
||||
where \c <category> is the name of the category, potentially with \c{*} as a
|
||||
wildcard symbol at the start and/or the end. The optional \c <type> must
|
||||
be either \c debug, \c warning, or \c critical.
|
||||
|
||||
The rules might be ignored if a custom category filter is installed with
|
||||
\l installFilter().
|
||||
*/
|
||||
void QLoggingCategory::setFilterRules(const QString &rules)
|
||||
{
|
||||
QLoggingRegistry::instance()->rulesParser.setRules(rules);
|
||||
}
|
||||
|
||||
/*!
|
||||
\macro qCDebug(category)
|
||||
\relates QLoggingCategory
|
||||
\since 5.2
|
||||
|
||||
Returns an output stream for debug messages in the logging category
|
||||
\a category.
|
||||
|
||||
The macro expands to code that first checks whether
|
||||
\l QLoggingCategory::isEnabled() evaluates for debug output to \c{true}.
|
||||
If so, the stream arguments are processed and sent to the message handler.
|
||||
|
||||
Example:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 10
|
||||
|
||||
\note Arguments are not processed if debug output for the category is not
|
||||
enabled, so do not rely on any side effects.
|
||||
|
||||
\sa qDebug()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro qCWarning(category)
|
||||
\relates QLoggingCategory
|
||||
\since 5.2
|
||||
|
||||
Returns an output stream for warning messages in the logging category
|
||||
\a category.
|
||||
|
||||
The macro expands to code that first checks whether
|
||||
\l QLoggingCategory::isEnabled() evaluates for warning output to \c{true}.
|
||||
If so, the stream arguments are processed and sent to the message handler.
|
||||
|
||||
Example:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 11
|
||||
|
||||
\note Arguments are not processed if warning output for the category is not
|
||||
enabled, so do not rely on any side effects.
|
||||
|
||||
\sa qWarning()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro qCCritical(category)
|
||||
\relates QLoggingCategory
|
||||
\since 5.2
|
||||
|
||||
Returns an output stream for critical messages in the logging category
|
||||
\a category.
|
||||
|
||||
The macro expands to code that first checks whether
|
||||
\l QLoggingCategory::isEnabled() evaluates for critical output to \c{true}.
|
||||
If so, the stream arguments are processed and sent to the message handler.
|
||||
|
||||
Example:
|
||||
|
||||
\snippet qloggingcategory/main.cpp 12
|
||||
|
||||
\note Arguments are not processed if critical output for the category is not
|
||||
enabled, so do not reply on any side effects.
|
||||
|
||||
\sa qCritical()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro Q_DECLARE_LOGGING_CATEGORY(name)
|
||||
\relates QLoggingCategory
|
||||
\since 5.2
|
||||
|
||||
Declares a logging category \a name. The macro can be used to declare
|
||||
a common logging category shared in different parts of the program.
|
||||
|
||||
This macro must be used outside of a class or method.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro Q_LOGGING_CATEGORY(name, string)
|
||||
\relates QLoggingCategory
|
||||
\since 5.2
|
||||
|
||||
Defines a logging category \a name, and makes it configurable under the
|
||||
\a string identifier.
|
||||
|
||||
Only one translation unit in a library or executable can define a category
|
||||
with a specific name.
|
||||
|
||||
This macro must be used outside of a class or method.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
138
src/corelib/io/qloggingcategory.h
Normal file
138
src/corelib/io/qloggingcategory.h
Normal file
@ -0,0 +1,138 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QLOGGINGCATEGORY_H
|
||||
#define QLOGGINGCATEGORY_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_CORE_EXPORT QLoggingCategory
|
||||
{
|
||||
Q_DISABLE_COPY(QLoggingCategory)
|
||||
public:
|
||||
explicit QLoggingCategory(const char *category);
|
||||
~QLoggingCategory();
|
||||
|
||||
template <QtMsgType T>
|
||||
bool isEnabled() const
|
||||
{
|
||||
return isEnabled(T);
|
||||
}
|
||||
|
||||
bool isEnabled(QtMsgType type) const;
|
||||
void setEnabled(QtMsgType type, bool enable);
|
||||
|
||||
const char *categoryName() const { return name; }
|
||||
|
||||
// allows usage of both factory method and variable in qCX macros
|
||||
QLoggingCategory &operator()() { return *this; }
|
||||
|
||||
static QLoggingCategory &defaultCategory();
|
||||
|
||||
typedef void (*CategoryFilter)(QLoggingCategory*);
|
||||
static CategoryFilter installFilter(CategoryFilter);
|
||||
|
||||
static void setFilterRules(const QString &rules);
|
||||
|
||||
private:
|
||||
const char *name;
|
||||
|
||||
bool enabledDebug;
|
||||
bool enabledWarning;
|
||||
bool enabledCritical;
|
||||
|
||||
friend class QLoggingRegistry;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool QLoggingCategory::isEnabled<QtDebugMsg>() const
|
||||
{
|
||||
return enabledDebug;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool QLoggingCategory::isEnabled<QtWarningMsg>() const
|
||||
{
|
||||
return enabledWarning;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool QLoggingCategory::isEnabled<QtCriticalMsg>() const
|
||||
{
|
||||
return enabledCritical;
|
||||
}
|
||||
|
||||
#define Q_DECLARE_LOGGING_CATEGORY(name) \
|
||||
extern QLoggingCategory &name();
|
||||
|
||||
// relies on QLoggingCategory(QString) being thread safe!
|
||||
#define Q_LOGGING_CATEGORY(name, string) \
|
||||
QLoggingCategory &name() \
|
||||
{ \
|
||||
static QLoggingCategory category(string); \
|
||||
return category; \
|
||||
}
|
||||
|
||||
#define qCDebug(category) \
|
||||
for (bool enabled = category().isEnabled<QtDebugMsg>(); enabled; enabled = false) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).debug()
|
||||
#define qCWarning(category) \
|
||||
for (bool enabled = category().isEnabled<QtWarningMsg>(); enabled; enabled = false) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).warning()
|
||||
#define qCCritical(category) \
|
||||
for (bool enabled = category().isEnabled<QtCriticalMsg>(); enabled; enabled = false) \
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical()
|
||||
|
||||
#if defined(QT_NO_DEBUG_OUTPUT)
|
||||
# undef qCDebug
|
||||
# define qCDebug(category) QT_NO_QDEBUG_MACRO()
|
||||
#endif
|
||||
#if defined(QT_NO_WARNING_OUTPUT)
|
||||
# undef qCWarning
|
||||
# define qCWarning(category) QT_NO_QWARNING_MACRO()
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QLOGGINGCATEGORY_H
|
66
src/corelib/io/qloggingcategory_p.h
Normal file
66
src/corelib/io/qloggingcategory_p.h
Normal file
@ -0,0 +1,66 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QLOGGINGCATEGORY_P_H
|
||||
#define QLOGGINGCATEGORY_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of a number of Qt sources files. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// unique pointer to default category
|
||||
// (allows to compare for pointers instead of strings)
|
||||
extern const char qtDefaultCategoryName[];
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QLOGGINGCATEGORY_P_H
|
312
src/corelib/io/qloggingregistry.cpp
Normal file
312
src/corelib/io/qloggingregistry.cpp
Normal file
@ -0,0 +1,312 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qloggingregistry_p.h"
|
||||
#include "qloggingcategory_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_GLOBAL_STATIC(QLoggingRegistry, qtLoggingRegistry)
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a logging rule with default values.
|
||||
*/
|
||||
QLoggingRule::QLoggingRule() :
|
||||
flags(Invalid),
|
||||
enabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a logging rule.
|
||||
*/
|
||||
QLoggingRule::QLoggingRule(const QString &pattern, bool enabled) :
|
||||
pattern(pattern),
|
||||
flags(Invalid),
|
||||
enabled(enabled)
|
||||
{
|
||||
parse();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Return value 1 means filter passed, 0 means filter doesn't influence this
|
||||
category, -1 means category doesn't pass this filter.
|
||||
*/
|
||||
int QLoggingRule::pass(const QString &categoryName, QtMsgType msgType) const
|
||||
{
|
||||
QString fullCategory = categoryName;
|
||||
switch (msgType) {
|
||||
case QtDebugMsg:
|
||||
fullCategory += QLatin1String(".debug");
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fullCategory += QLatin1String(".warning");
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fullCategory += QLatin1String(".critical");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags == FullText) {
|
||||
// can be
|
||||
// qtproject.org.debug = true
|
||||
// or
|
||||
// qtproject.org = true
|
||||
if (pattern == categoryName
|
||||
|| pattern == fullCategory)
|
||||
return (enabled ? 1 : -1);
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
if (flags == MidFilter) {
|
||||
// e.g. *.qtproject*
|
||||
idx = fullCategory.indexOf(pattern);
|
||||
if (idx >= 0)
|
||||
return (enabled ? 1 : -1);
|
||||
} else {
|
||||
idx = fullCategory.indexOf(pattern);
|
||||
if (flags == LeftFilter) {
|
||||
// e.g. org.qtproject.*
|
||||
if (idx == 0)
|
||||
return (enabled ? 1 : -1);
|
||||
} else if (flags == RightFilter) {
|
||||
// e.g. *.qtproject
|
||||
if (idx == (fullCategory.count() - pattern.count()))
|
||||
return (enabled ? 1 : -1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Parses the category and checks which kind of wildcard the filter can contain.
|
||||
Allowed is f.ex.:
|
||||
org.qtproject.logging FullText
|
||||
org.qtproject.* LeftFilter
|
||||
*.qtproject RightFilter
|
||||
*.qtproject* MidFilter
|
||||
*/
|
||||
void QLoggingRule::parse()
|
||||
{
|
||||
int index = pattern.indexOf(QLatin1Char('*'));
|
||||
if (index < 0) {
|
||||
flags = FullText;
|
||||
} else {
|
||||
flags = Invalid;
|
||||
if (index == 0) {
|
||||
flags |= RightFilter;
|
||||
pattern = pattern.remove(0, 1);
|
||||
index = pattern.indexOf(QLatin1Char('*'));
|
||||
}
|
||||
if (index == (pattern.length() - 1)) {
|
||||
flags |= LeftFilter;
|
||||
pattern = pattern.remove(pattern.length() - 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Creates a new QLoggingRules object.
|
||||
*/
|
||||
QLoggingRulesParser::QLoggingRulesParser(QLoggingRegistry *registry) :
|
||||
registry(registry)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Sets logging rules string.
|
||||
*/
|
||||
void QLoggingRulesParser::setRules(const QString &content)
|
||||
{
|
||||
QString content_ = content;
|
||||
QTextStream stream(&content_, QIODevice::ReadOnly);
|
||||
parseRules(stream);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Parses rules out of a QTextStream.
|
||||
*/
|
||||
void QLoggingRulesParser::parseRules(QTextStream &stream)
|
||||
{
|
||||
QVector<QLoggingRule> rules;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
QString line = stream.readLine();
|
||||
|
||||
// Remove all whitespace from line
|
||||
line = line.simplified();
|
||||
line.remove(QLatin1Char(' '));
|
||||
|
||||
const QStringList pair = line.split(QLatin1Char('='));
|
||||
if (pair.count() == 2) {
|
||||
const QString pattern = pair.at(0);
|
||||
bool enabled = (QString::compare(pair.at(1),
|
||||
QLatin1String("true"),
|
||||
Qt::CaseInsensitive) == 0);
|
||||
rules.append(QLoggingRule(pattern, enabled));
|
||||
}
|
||||
}
|
||||
|
||||
registry->setRules(rules);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
QLoggingPrivate constructor
|
||||
*/
|
||||
QLoggingRegistry::QLoggingRegistry()
|
||||
: rulesParser(this),
|
||||
categoryFilter(defaultCategoryFilter)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Registers a category object.
|
||||
|
||||
This method might be called concurrently for the same category object.
|
||||
*/
|
||||
void QLoggingRegistry::registerCategory(QLoggingCategory *cat)
|
||||
{
|
||||
QMutexLocker locker(®istryMutex);
|
||||
|
||||
if (!categories.contains(cat)) {
|
||||
categories.append(cat);
|
||||
(*categoryFilter)(cat);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Unregisters a category object.
|
||||
*/
|
||||
void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat)
|
||||
{
|
||||
QMutexLocker locker(®istryMutex);
|
||||
|
||||
categories.removeOne(cat);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Activates a new set of logging rules for the default filter.
|
||||
*/
|
||||
void QLoggingRegistry::setRules(const QVector<QLoggingRule> &rules_)
|
||||
{
|
||||
QMutexLocker locker(®istryMutex);
|
||||
|
||||
rules = rules_;
|
||||
|
||||
if (categoryFilter != defaultCategoryFilter)
|
||||
return;
|
||||
|
||||
foreach (QLoggingCategory *cat, categories)
|
||||
(*categoryFilter)(cat);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Installs a custom filter rule.
|
||||
*/
|
||||
QLoggingCategory::CategoryFilter
|
||||
QLoggingRegistry::installFilter(QLoggingCategory::CategoryFilter filter)
|
||||
{
|
||||
QMutexLocker locker(®istryMutex);
|
||||
|
||||
if (filter == 0)
|
||||
filter = defaultCategoryFilter;
|
||||
|
||||
QLoggingCategory::CategoryFilter old = categoryFilter;
|
||||
categoryFilter = filter;
|
||||
|
||||
foreach (QLoggingCategory *cat, categories)
|
||||
(*categoryFilter)(cat);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
QLoggingRegistry *QLoggingRegistry::instance()
|
||||
{
|
||||
return qtLoggingRegistry();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Updates category settings according to rules.
|
||||
*/
|
||||
void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
|
||||
{
|
||||
// QLoggingCategory() normalizes all "default" strings
|
||||
// to qtDefaultCategoryName
|
||||
bool debug = (cat->categoryName() == qtDefaultCategoryName);
|
||||
bool warning = true;
|
||||
bool critical = true;
|
||||
|
||||
QString categoryName = QLatin1String(cat->categoryName());
|
||||
QLoggingRegistry *reg = QLoggingRegistry::instance();
|
||||
foreach (const QLoggingRule &item, reg->rules) {
|
||||
int filterpass = item.pass(categoryName, QtDebugMsg);
|
||||
if (filterpass != 0)
|
||||
debug = (filterpass > 0);
|
||||
filterpass = item.pass(categoryName, QtWarningMsg);
|
||||
if (filterpass != 0)
|
||||
warning = (filterpass > 0);
|
||||
filterpass = item.pass(categoryName, QtCriticalMsg);
|
||||
if (filterpass != 0)
|
||||
critical = (filterpass > 0);
|
||||
}
|
||||
|
||||
cat->setEnabled(QtDebugMsg, debug);
|
||||
cat->setEnabled(QtWarningMsg, warning);
|
||||
cat->setEnabled(QtCriticalMsg, critical);
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
135
src/corelib/io/qloggingregistry_p.h
Normal file
135
src/corelib/io/qloggingregistry_p.h
Normal file
@ -0,0 +1,135 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QLOGGINGREGISTRY_P_H
|
||||
#define QLOGGINGREGISTRY_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of a number of Qt sources files. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qtextstream.h>
|
||||
#include <QtCore/qvector.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QLoggingRule
|
||||
{
|
||||
public:
|
||||
QLoggingRule();
|
||||
QLoggingRule(const QString &pattern, bool enabled);
|
||||
int pass(const QString &categoryName, QtMsgType type) const;
|
||||
|
||||
enum PatternFlag {
|
||||
Invalid = 0x0,
|
||||
FullText = 0x1,
|
||||
LeftFilter = 0x2,
|
||||
RightFilter = 0x4,
|
||||
MidFilter = LeftFilter | RightFilter
|
||||
};
|
||||
Q_DECLARE_FLAGS(PatternFlags, PatternFlag)
|
||||
|
||||
QString pattern;
|
||||
PatternFlags flags;
|
||||
bool enabled;
|
||||
|
||||
private:
|
||||
void parse();
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags)
|
||||
Q_DECLARE_TYPEINFO(QLoggingRule, Q_MOVABLE_TYPE);
|
||||
|
||||
class QLoggingRulesParser
|
||||
{
|
||||
private:
|
||||
explicit QLoggingRulesParser(class QLoggingRegistry *logging);
|
||||
|
||||
public:
|
||||
void setRules(const QString &content);
|
||||
|
||||
private:
|
||||
void parseRules(QTextStream &stream);
|
||||
QLoggingRegistry *registry;
|
||||
|
||||
friend class QLoggingRegistry;
|
||||
};
|
||||
|
||||
class QLoggingRegistry
|
||||
{
|
||||
public:
|
||||
QLoggingRegistry();
|
||||
|
||||
void registerCategory(QLoggingCategory *category);
|
||||
void unregisterCategory(QLoggingCategory *category);
|
||||
|
||||
void setRules(const QVector<QLoggingRule> &rules);
|
||||
|
||||
QLoggingCategory::CategoryFilter
|
||||
installFilter(QLoggingCategory::CategoryFilter filter);
|
||||
|
||||
static QLoggingRegistry *instance();
|
||||
|
||||
QLoggingRulesParser rulesParser;
|
||||
|
||||
private:
|
||||
static void defaultCategoryFilter(QLoggingCategory *category);
|
||||
|
||||
QMutex registryMutex;
|
||||
QVector<QLoggingRule> rules;
|
||||
QList<QLoggingCategory*> categories;
|
||||
QLoggingCategory::CategoryFilter categoryFilter;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QLOGGINGREGISTRY_P_H
|
@ -16,6 +16,7 @@ SUBDIRS=\
|
||||
qiodevice \
|
||||
qipaddress \
|
||||
qlockfile \
|
||||
qloggingcategory \
|
||||
qnodebug \
|
||||
qprocess \
|
||||
qprocess-noapplication \
|
||||
|
@ -0,0 +1,7 @@
|
||||
TEMPLATE = app
|
||||
TARGET = tst_qloggingcategory
|
||||
|
||||
CONFIG += testcase
|
||||
QT = core core-private testlib
|
||||
|
||||
SOURCES += tst_qloggingcategory.cpp
|
818
tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
Normal file
818
tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
Normal file
@ -0,0 +1,818 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QMutexLocker>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_LOGGING_CATEGORY(TST_LOG, "tst.log")
|
||||
Q_LOGGING_CATEGORY(TST_LOG1, "tst.log1")
|
||||
Q_LOGGING_CATEGORY(Digia_Oslo_Office_com, "Digia.Oslo.Office.com")
|
||||
Q_LOGGING_CATEGORY(Digia_Oulu_Office_com, "Digia.Oulu.Office.com")
|
||||
Q_LOGGING_CATEGORY(Digia_Berlin_Office_com, "Digia.Berlin.Office.com")
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
QtMessageHandler oldMessageHandler;
|
||||
QString logMessage;
|
||||
bool multithreadtest = false;
|
||||
QStringList threadtest;
|
||||
QMutex threadmutex;
|
||||
bool usedefaultformat = false;
|
||||
|
||||
QByteArray qMyMessageFormatString(QtMsgType type, const QMessageLogContext &context,
|
||||
const QString &str)
|
||||
{
|
||||
QByteArray message;
|
||||
if (!usedefaultformat) {
|
||||
message.append(context.category);
|
||||
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;
|
||||
}
|
||||
message.append(": ");
|
||||
message.append(qPrintable(str));
|
||||
} else {
|
||||
message.append(qPrintable(str));
|
||||
}
|
||||
|
||||
return message.simplified();
|
||||
}
|
||||
|
||||
static void myCustomMessageHandler(QtMsgType type,
|
||||
const QMessageLogContext &context,
|
||||
const QString &msg)
|
||||
{
|
||||
QMutexLocker locker(&threadmutex);
|
||||
logMessage = qMyMessageFormatString(type, context, msg);
|
||||
if (multithreadtest)
|
||||
threadtest.append(logMessage);
|
||||
}
|
||||
|
||||
class Configuration
|
||||
{
|
||||
public:
|
||||
Configuration()
|
||||
{
|
||||
}
|
||||
|
||||
void addKey(const QString &key, bool val){
|
||||
// Old key values gets updated
|
||||
_values.insert(key, (val ? "true" : "false"));
|
||||
if (!_configitemEntryOrder.contains(key))
|
||||
_configitemEntryOrder.append(key);
|
||||
}
|
||||
|
||||
void addKey(const QString &key, const QString &val){
|
||||
// Old key values gets updated
|
||||
_values.insert(key, val);
|
||||
if (!_configitemEntryOrder.contains(key))
|
||||
_configitemEntryOrder.append(key);
|
||||
}
|
||||
|
||||
QByteArray array()
|
||||
{
|
||||
QString ret;
|
||||
QTextStream out(&ret);
|
||||
for (int a = 0; a < _configitemEntryOrder.count(); a++) {
|
||||
out << _configitemEntryOrder[a]
|
||||
<< " = "
|
||||
<< _values.value(_configitemEntryOrder[a]) << endl;
|
||||
}
|
||||
out.flush();
|
||||
return ret.toLatin1();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_values.clear();
|
||||
_configitemEntryOrder.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
QMap<QString, QString> _values;
|
||||
QStringList _configitemEntryOrder;
|
||||
};
|
||||
|
||||
static Configuration configuration1;
|
||||
static Configuration configuration2;
|
||||
|
||||
class LogThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LogThread(const QString &logtext, Configuration *configuration)
|
||||
: _logtext(logtext), _configuration(configuration)
|
||||
{}
|
||||
protected:
|
||||
void run()
|
||||
{
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
_configuration->addKey("Digia*", true);
|
||||
QByteArray arr = _configuration->array();
|
||||
QLoggingCategory::setFilterRules(arr);
|
||||
qCDebug(Digia_Oslo_Office_com) << "Oslo " << _logtext << " :true";
|
||||
_configuration->addKey("Digia*", false);
|
||||
arr = _configuration->array();
|
||||
QLoggingCategory::setFilterRules(arr);
|
||||
qCDebug(Digia_Oslo_Office_com) << "Oslo " << _logtext << " :false";
|
||||
|
||||
_configuration->addKey("Digia*", true);
|
||||
arr = _configuration->array();
|
||||
QLoggingCategory::setFilterRules(arr);
|
||||
qCDebug(Digia_Berlin_Office_com) << "Berlin " << _logtext << " :true";
|
||||
_configuration->addKey("Digia*", false);
|
||||
arr = _configuration->array();
|
||||
QLoggingCategory::setFilterRules(arr);
|
||||
qCDebug(Digia_Berlin_Office_com) << "Berlin " << _logtext << " :false";
|
||||
|
||||
_configuration->addKey("Digia*", true);
|
||||
arr = _configuration->array();
|
||||
QLoggingCategory::setFilterRules(arr);
|
||||
qCDebug(Digia_Oulu_Office_com) << "Oulu " << _logtext << " :true";
|
||||
_configuration->addKey("Digia*", false);
|
||||
arr = _configuration->array();
|
||||
QLoggingCategory::setFilterRules(arr);
|
||||
qCDebug(Digia_Oulu_Office_com) << "Oulu " << _logtext << " :false";
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
QString _logtext;
|
||||
Configuration *_configuration;
|
||||
};
|
||||
|
||||
inline QString cleanLogLine(const QString &qstring)
|
||||
{
|
||||
QString buf = qstring;
|
||||
buf.remove("../");
|
||||
buf.remove("qlog/");
|
||||
QString ret;
|
||||
for (int i = 0; i < buf.length(); i++) {
|
||||
if (buf[i] >= '!' && buf[i] <= 'z')
|
||||
ret += buf[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QStringList customCategoryFilterArgs;
|
||||
static void customCategoryFilter(QLoggingCategory *category)
|
||||
{
|
||||
customCategoryFilterArgs << QLatin1String(category->categoryName());
|
||||
// invert debug
|
||||
category->setEnabled(QtDebugMsg, !category->isEnabled(QtDebugMsg));
|
||||
}
|
||||
|
||||
class tst_QLogging : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
Configuration *_config;
|
||||
QStringList logEntries;
|
||||
|
||||
private slots:
|
||||
void initTestCase()
|
||||
{
|
||||
qputenv("QT_MESSAGE_PATTERN", QByteArray("%{category}: %{type},%{message}"));
|
||||
oldMessageHandler = qInstallMessageHandler(myCustomMessageHandler);
|
||||
// Create configuration
|
||||
_config = new Configuration();
|
||||
}
|
||||
|
||||
void QLoggingCategory_categoryName()
|
||||
{
|
||||
logMessage.clear();
|
||||
QCOMPARE(QString::fromLatin1(QLoggingCategory::defaultCategory().categoryName()),
|
||||
QStringLiteral("default"));
|
||||
|
||||
QLoggingCategory defaultCategory("default");
|
||||
QCOMPARE(QString::fromLatin1(defaultCategory.categoryName()),
|
||||
QStringLiteral("default"));
|
||||
|
||||
QLoggingCategory nullCategory(0);
|
||||
QCOMPARE(QByteArray(nullCategory.categoryName()), QByteArray("default"));
|
||||
|
||||
// we rely on the same pointer for any "default" category
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().categoryName(),
|
||||
defaultCategory.categoryName());
|
||||
QCOMPARE(defaultCategory.categoryName(),
|
||||
nullCategory.categoryName());
|
||||
|
||||
QLoggingCategory customCategory("custom");
|
||||
QCOMPARE(QByteArray(customCategory.categoryName()), QByteArray("custom"));
|
||||
|
||||
QLoggingCategory emptyCategory("");
|
||||
QCOMPARE(QByteArray(emptyCategory.categoryName()), QByteArray(""));
|
||||
|
||||
// make sure nothing has printed warnings
|
||||
QVERIFY(logMessage.isEmpty());
|
||||
}
|
||||
|
||||
void QLoggingCategory_isEnabled()
|
||||
{
|
||||
logMessage.clear();
|
||||
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled<QtDebugMsg>(), true);
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled(QtDebugMsg), true);
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled<QtWarningMsg>(), true);
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled(QtWarningMsg), true);
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled<QtCriticalMsg>(), true);
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled(QtCriticalMsg), true);
|
||||
|
||||
QLoggingCategory defaultCategory("default");
|
||||
QCOMPARE(defaultCategory.isEnabled<QtDebugMsg>(), true);
|
||||
QCOMPARE(defaultCategory.isEnabled(QtDebugMsg), true);
|
||||
QCOMPARE(defaultCategory.isEnabled<QtWarningMsg>(), true);
|
||||
QCOMPARE(defaultCategory.isEnabled(QtWarningMsg), true);
|
||||
QCOMPARE(defaultCategory.isEnabled<QtCriticalMsg>(), true);
|
||||
QCOMPARE(defaultCategory.isEnabled(QtCriticalMsg), true);
|
||||
|
||||
QLoggingCategory customCategory("custom");
|
||||
QCOMPARE(customCategory.isEnabled<QtDebugMsg>(), false);
|
||||
QCOMPARE(customCategory.isEnabled(QtDebugMsg), false);
|
||||
QCOMPARE(customCategory.isEnabled<QtWarningMsg>(), true);
|
||||
QCOMPARE(customCategory.isEnabled(QtWarningMsg), true);
|
||||
QCOMPARE(customCategory.isEnabled<QtCriticalMsg>(), true);
|
||||
QCOMPARE(customCategory.isEnabled(QtCriticalMsg), true);
|
||||
|
||||
// make sure nothing has printed warnings
|
||||
QVERIFY(logMessage.isEmpty());
|
||||
}
|
||||
|
||||
void QLoggingCategory_setEnabled()
|
||||
{
|
||||
logMessage.clear();
|
||||
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled<QtDebugMsg>(), true);
|
||||
|
||||
QLoggingCategory::defaultCategory().setEnabled(QtDebugMsg, false);
|
||||
QCOMPARE(QLoggingCategory::defaultCategory().isEnabled<QtDebugMsg>(), false);
|
||||
QLoggingCategory::defaultCategory().setEnabled(QtDebugMsg, true);
|
||||
|
||||
// make sure nothing has printed warnings
|
||||
QVERIFY(logMessage.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
void QLoggingCategory_installFilter()
|
||||
{
|
||||
QVERIFY(QLoggingCategory::defaultCategory().isEnabled<QtDebugMsg>());
|
||||
|
||||
QLoggingCategory::CategoryFilter defaultFilter =
|
||||
QLoggingCategory::installFilter(customCategoryFilter);
|
||||
QVERIFY(defaultFilter);
|
||||
customCategoryFilterArgs.clear();
|
||||
QVERIFY(!QLoggingCategory::defaultCategory().isEnabled<QtDebugMsg>());
|
||||
|
||||
QLoggingCategory cat("custom");
|
||||
QCOMPARE(customCategoryFilterArgs, QStringList() << "custom");
|
||||
QVERIFY(cat.isEnabled<QtDebugMsg>());
|
||||
customCategoryFilterArgs.clear();
|
||||
|
||||
// install default filter
|
||||
QLoggingCategory::CategoryFilter currentFilter =
|
||||
QLoggingCategory::installFilter(defaultFilter);
|
||||
QCOMPARE((void*)currentFilter, (void*)customCategoryFilter);
|
||||
QCOMPARE(customCategoryFilterArgs.size(), 0);
|
||||
|
||||
QVERIFY(QLoggingCategory::defaultCategory().isEnabled<QtDebugMsg>());
|
||||
QVERIFY(!cat.isEnabled<QtDebugMsg>());
|
||||
|
||||
// install default filter
|
||||
currentFilter =
|
||||
QLoggingCategory::installFilter(0);
|
||||
QCOMPARE((void*)defaultFilter, (void*)currentFilter);
|
||||
QCOMPARE(customCategoryFilterArgs.size(), 0);
|
||||
|
||||
QVERIFY(QLoggingCategory::defaultCategory().isEnabled<QtDebugMsg>());
|
||||
QVERIFY(!cat.isEnabled<QtDebugMsg>());
|
||||
}
|
||||
|
||||
void qDebugMacros()
|
||||
{
|
||||
QString buf;
|
||||
|
||||
// Check default debug
|
||||
buf = QStringLiteral("default.debug: Check debug with no filter active");
|
||||
qDebug("%s", "Check debug with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check default warning
|
||||
buf = QStringLiteral("default.warning: Check warning with no filter active");
|
||||
qWarning("%s", "Check warning with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check default critical
|
||||
buf = QStringLiteral("default.critical: Check critical with no filter active");
|
||||
qCritical("%s", "Check critical with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// install filter (inverts rules for qtdebug)
|
||||
QLoggingCategory::installFilter(customCategoryFilter);
|
||||
|
||||
// Check default debug
|
||||
logMessage.clear();
|
||||
qDebug("%s", "Check debug with filter active");
|
||||
QCOMPARE(logMessage, QString());
|
||||
|
||||
// reset to default filter
|
||||
QLoggingCategory::installFilter(0);
|
||||
|
||||
// Check default debug
|
||||
buf = QStringLiteral("default.debug: Check debug with no filter active");
|
||||
qDebug("%s", "Check debug with no filter active");
|
||||
QCOMPARE(logMessage, buf);
|
||||
}
|
||||
|
||||
void qCDebugMacros()
|
||||
{
|
||||
QString buf;
|
||||
|
||||
QLoggingCategory defaultCategory("default");
|
||||
// Check default debug
|
||||
buf = QStringLiteral("default.debug: Check debug with no filter active");
|
||||
qCDebug(defaultCategory) << "Check debug with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check default warning
|
||||
buf = QStringLiteral("default.warning: Check warning with no filter active");
|
||||
qCWarning(defaultCategory) << "Check warning with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check default critical
|
||||
buf = QStringLiteral("default.critical: Check critical with no filter active");
|
||||
qCCritical(defaultCategory) << "Check critical with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
|
||||
QLoggingCategory customCategory("custom");
|
||||
// Check custom debug
|
||||
logMessage.clear();
|
||||
qCDebug(customCategory) << "Check debug with no filter active";
|
||||
QCOMPARE(logMessage, QString());
|
||||
|
||||
// Check custom warning
|
||||
buf = QStringLiteral("custom.warning: Check warning with no filter active");
|
||||
qCWarning(customCategory) << "Check warning with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check custom critical
|
||||
buf = QStringLiteral("custom.critical: Check critical with no filter active");
|
||||
qCCritical(customCategory) << "Check critical with no filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// install filter (inverts rules for qtdebug)
|
||||
QLoggingCategory::installFilter(customCategoryFilter);
|
||||
|
||||
// Check custom debug
|
||||
buf = QStringLiteral("custom.debug: Check debug with filter active");
|
||||
qCDebug(customCategory) << "Check debug with filter active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// reset to default filter
|
||||
QLoggingCategory::installFilter(0);
|
||||
|
||||
// Check custom debug
|
||||
logMessage.clear();
|
||||
qCDebug(customCategory) << "Check debug with no filter active";
|
||||
QCOMPARE(logMessage, QString());
|
||||
}
|
||||
|
||||
void checkLegacyMessageLogger()
|
||||
{
|
||||
usedefaultformat = true;
|
||||
// This should just not crash.
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug() << "checkLegacyMessageLogger1";
|
||||
QCOMPARE(logMessage, QStringLiteral("checkLegacyMessageLogger1"));
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).warning() << "checkLegacyMessageLogger2";
|
||||
QCOMPARE(logMessage, QStringLiteral("checkLegacyMessageLogger2"));
|
||||
QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).critical() << "checkLegacyMessageLogger3";
|
||||
QCOMPARE(logMessage, QStringLiteral("checkLegacyMessageLogger3"));
|
||||
usedefaultformat = false;
|
||||
}
|
||||
|
||||
// Check the Debug, Warning and critical without having category active. should be active.
|
||||
void checkNoCategoryLogActive()
|
||||
{
|
||||
// Check default debug
|
||||
QString buf = QStringLiteral("default.debug: Check default Debug with no log active");
|
||||
qDebug() << "Check default Debug with no log active";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check default warning
|
||||
buf = QStringLiteral("default.warning: Check default Warning with no log active");
|
||||
qWarning() << "Check default Warning with no log active";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check default critical
|
||||
buf = QStringLiteral("default.critical: Check default Critical with no log active");
|
||||
qCritical() << "Check default Critical with no log active";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check category debug
|
||||
logMessage = "should not change";
|
||||
buf = logMessage;
|
||||
qCDebug(TST_LOG) << "Check category Debug with no log active";
|
||||
QCOMPARE(logMessage, buf);
|
||||
|
||||
// Check default warning
|
||||
buf = QStringLiteral("tst.log.warning: Check category Warning with no log active");
|
||||
qCWarning(TST_LOG) << "Check category Warning with no log active";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check default critical
|
||||
buf = QStringLiteral("tst.log.critical: Check category Critical with no log active");
|
||||
qCCritical(TST_LOG) << "Check category Critical with no log active";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
}
|
||||
|
||||
void writeCategoryLogs()
|
||||
{
|
||||
usedefaultformat = false;
|
||||
// Activate TST_LOG category
|
||||
logMessage = "";
|
||||
_config->addKey("tst.log", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
QString buf = QStringLiteral("tst.log.debug: Check for default messagePattern");
|
||||
qCDebug(TST_LOG) << "Check for default messagePattern";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Activate TST_LOG category with default enabled function info
|
||||
_config->addKey("tst.log1", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
qCDebug(TST_LOG) << "1";
|
||||
buf = QStringLiteral("tst.log.debug: 1");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Write out all different types
|
||||
qCDebug(TST_LOG) << "DebugType";
|
||||
buf = QStringLiteral("tst.log.debug: DebugType");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCWarning(TST_LOG) << "WarningType";
|
||||
buf = QStringLiteral("tst.log.warning: WarningType");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCCritical(TST_LOG) << "CriticalType";
|
||||
buf = QStringLiteral("tst.log.critical: CriticalType");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
}
|
||||
|
||||
void checkLegacyLogs()
|
||||
{
|
||||
logMessage = "";
|
||||
qDebug() << "DefaultDebug";
|
||||
QString buf = QStringLiteral("default.debug: DefaultDebug");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// debug off by default, warning and critical are on
|
||||
qWarning() << "DefaultWarning";
|
||||
buf = QStringLiteral("default.warning: DefaultWarning");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCritical() << "DefaultCritical";
|
||||
buf = QStringLiteral("default.critical: DefaultCritical");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Enable debug
|
||||
_config->addKey("default.debug", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
qDebug() << "DefaultDebug1";
|
||||
buf = QStringLiteral("default.debug: DefaultDebug1");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qWarning() << "DefaultWarning1";
|
||||
buf = QStringLiteral("default.warning: DefaultWarning1");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCritical() << "DefaultCritical1";
|
||||
buf = QStringLiteral("default.critical: DefaultCritical1");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Disable warning
|
||||
_config->addKey("default.warning", false);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
qDebug() << "DefaultDebug2";
|
||||
buf = QStringLiteral("default.debug: DefaultDebug2");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
logMessage = "no change";
|
||||
qWarning() << "DefaultWarning2";
|
||||
buf = QStringLiteral("no change");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCritical() << "DefaultCritical2";
|
||||
buf = QStringLiteral("default.critical: DefaultCritical2");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Disable critical
|
||||
_config->addKey("default.critical", false);
|
||||
_config->addKey("default.debug", false);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
logMessage = "no change";
|
||||
qDebug() << "DefaultDebug3";
|
||||
buf = QStringLiteral("no change");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qWarning() << "DefaultWarning3";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCritical() << "DefaultCritical3";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Enable default logs
|
||||
_config->addKey("default.critical", true);
|
||||
_config->addKey("default.warning", true);
|
||||
_config->addKey("default.debug", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
// Ensure all are on
|
||||
qDebug() << "DefaultDebug4";
|
||||
buf = QStringLiteral("default.debug: DefaultDebug4");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qWarning() << "DefaultWarning4";
|
||||
buf = QStringLiteral("default.warning: DefaultWarning4");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCritical() << "DefaultCritical4";
|
||||
buf = QStringLiteral("default.critical: DefaultCritical4");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Disable default log
|
||||
_config->addKey("default", false);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
// Ensure all are off
|
||||
logMessage = "no change";
|
||||
buf = QStringLiteral("no change");
|
||||
qDebug() << "DefaultDebug5";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qWarning() << "DefaultWarning5";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCritical() << "DefaultCritical5";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Reset
|
||||
_config->clear();
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
}
|
||||
|
||||
void checkFiltering()
|
||||
{
|
||||
// Enable default logs
|
||||
_config->clear();
|
||||
_config->addKey("Digia.Oslo.Office.com", false);
|
||||
_config->addKey("Digia.Oulu.Office.com", false);
|
||||
_config->addKey("Digia.Berlin.Office.com", false);
|
||||
_config->addKey("MessagePattern", QString("%{category}: %{message}"));
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
logMessage = "no change";
|
||||
QString buf = QStringLiteral("no change");
|
||||
qCDebug(Digia_Oslo_Office_com) << "Digia.Oslo.Office.com 1";
|
||||
qCDebug(Digia_Oulu_Office_com) << "Digia.Oulu.Office.com 1";
|
||||
qCDebug(Digia_Berlin_Office_com) << "Digia.Berlin.Office.com 1";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
_config->addKey("Digia.Oslo.Office.com", true);
|
||||
_config->addKey("Digia.Oulu.Office.com", true);
|
||||
_config->addKey("Digia.Berlin.Office.com", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
qCDebug(Digia_Oslo_Office_com) << "Digia.Oslo.Office.com 2";
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Digia.Oslo.Office.com 2");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCDebug(Digia_Oulu_Office_com) << "Digia.Oulu.Office.com 2";
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.debug: Digia.Oulu.Office.com 2");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCDebug(Digia_Berlin_Office_com) << "Digia.Berlin.Office.com 2";
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.debug: Digia.Berlin.Office.com 2");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check right filter
|
||||
_config->addKey("Digia.Oslo.Office.com", false);
|
||||
_config->addKey("Digia.Oulu.Office.com", false);
|
||||
_config->addKey("Digia.Berlin.Office.com", false);
|
||||
_config->addKey("*Office.com*", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
qCDebug(Digia_Oslo_Office_com) << "Digia.Oslo.Office.com 3";
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Digia.Oslo.Office.com 3");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCDebug(Digia_Oulu_Office_com) << "Digia.Oulu.Office.com 3";
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.debug: Digia.Oulu.Office.com 3");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCDebug(Digia_Berlin_Office_com) << "Digia.Berlin.Office.com 3";
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.debug: Digia.Berlin.Office.com 3");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check left filter
|
||||
_config->addKey("*Office.com*", false);
|
||||
_config->addKey("*Office.com.debug", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
qCDebug(Digia_Oslo_Office_com) << "Debug: Digia.Oslo.Office.com 4";
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Debug: Digia.Oslo.Office.com 4");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
logMessage = "no change";
|
||||
buf = QStringLiteral("no change");
|
||||
qCWarning(Digia_Oulu_Office_com) << "Warning: Digia.Oulu.Office.com 4";
|
||||
qCCritical(Digia_Berlin_Office_com) << "Critical: Digia.Berlin.Office.com 4";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check right filter
|
||||
_config->addKey("*Office.com.debug", false);
|
||||
_config->addKey("Digia.*", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
qCDebug(Digia_Oslo_Office_com) << "Debug: Digia.Oslo.Office.com 5";
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Debug: Digia.Oslo.Office.com 5");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCWarning(Digia_Oulu_Office_com) << "Warning: Digia.Oulu.Office.com 5";
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.warning: Warning: Digia.Oulu.Office.com 5");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCCritical(Digia_Berlin_Office_com) << "Critical: Digia.Berlin.Office.com 5";
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.critical: Critical: Digia.Berlin.Office.com 5");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// Check mid filter
|
||||
_config->addKey("Digia.*", false);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
logMessage = "no change";
|
||||
buf = QStringLiteral("no change");
|
||||
qCDebug(Digia_Oslo_Office_com) << "Debug: Digia.Oslo.Office.com 6";
|
||||
qCWarning(Digia_Oulu_Office_com) << "Warning: Digia.Oulu.Office.com 6";
|
||||
qCCritical(Digia_Berlin_Office_com) << "Critical: Digia.Berlin.Office.com 6";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
_config->addKey("*.Office.*", true);
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
|
||||
qCDebug(Digia_Oslo_Office_com) << "Debug: Digia.Oslo.Office.com 7";
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Debug: Digia.Oslo.Office.com 7");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCWarning(Digia_Oulu_Office_com) << "Warning: Digia.Oulu.Office.com 7";
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.warning: Warning: Digia.Oulu.Office.com 7");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
qCCritical(Digia_Berlin_Office_com) << "Critical: Digia.Berlin.Office.com 7";
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.critical: Critical: Digia.Berlin.Office.com 7");
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
}
|
||||
|
||||
void checkLogWithCategoryObject()
|
||||
{
|
||||
_config->clear();
|
||||
_config->addKey("LoggingCategoryObject", true);
|
||||
QLoggingCategory *pcategorybject = 0;
|
||||
QLoggingCategory::setFilterRules(_config->array());
|
||||
{
|
||||
QLoggingCategory mycategoryobject("LoggingCategoryObject");
|
||||
pcategorybject = &mycategoryobject;
|
||||
logMessage = "no change";
|
||||
|
||||
QString buf = QStringLiteral("LoggingCategoryObject.debug: My Category Object");
|
||||
qCDebug(mycategoryobject) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
buf = QStringLiteral("LoggingCategoryObject.warning: My Category Object");
|
||||
qCWarning(mycategoryobject) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
buf = QStringLiteral("LoggingCategoryObject.critical: My Category Object");
|
||||
qCCritical(mycategoryobject) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
QLoggingCategory mycategoryobject2("LoggingCategoryObject");
|
||||
buf = QStringLiteral("LoggingCategoryObject.debug: My Category Object");
|
||||
qCDebug(mycategoryobject) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
buf = QStringLiteral("LoggingCategoryObject.warning: My Category Object");
|
||||
qCWarning(mycategoryobject) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
buf = QStringLiteral("LoggingCategoryObject.critical: My Category Object");
|
||||
qCCritical(mycategoryobject) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
}
|
||||
}
|
||||
|
||||
void checkEmptyCategoryName()
|
||||
{
|
||||
// "" -> custom category
|
||||
QLoggingCategory mycategoryobject1("");
|
||||
logMessage = "no change";
|
||||
QString buf = QStringLiteral("no change");
|
||||
qCDebug(mycategoryobject1) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
|
||||
// 0 -> default category
|
||||
QLoggingCategory mycategoryobject2(0);
|
||||
buf = QStringLiteral("default.debug:MyCategoryObject");
|
||||
qCDebug(mycategoryobject2) << "My Category Object";
|
||||
QCOMPARE(cleanLogLine(logMessage), cleanLogLine(buf));
|
||||
}
|
||||
|
||||
void checkMultithreading()
|
||||
{
|
||||
multithreadtest = true;
|
||||
// Init two configurations, one for each thread
|
||||
configuration1.addKey("Digia*", true);
|
||||
configuration2.addKey("Digia*", true);
|
||||
QByteArray arr = configuration1.array();
|
||||
QLoggingCategory::setFilterRules(arr);
|
||||
|
||||
LogThread thgread1(QString("from Thread 1"), &configuration1);
|
||||
LogThread thgread2(QString("from Thread 2"), &configuration2);
|
||||
|
||||
// Writing out stuff from 2 different threads into the same areas
|
||||
thgread1.start();
|
||||
thgread2.start();
|
||||
thgread1.wait();
|
||||
thgread2.wait();
|
||||
|
||||
// Check if each log line is complete
|
||||
QStringList compareagainst;
|
||||
QString buf = QStringLiteral("Digia.Oslo.Office.com.debug: Oslo \"from Thread 1\" :true");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.debug: Oulu \"from Thread 1\" :true");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.debug: Berlin \"from Thread 1\" :true");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Oslo \"from Thread 1\" :false");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.debug: Oulu \"from Thread 1\" :false");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.debug: Berlin \"from Thread 1\" :false");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Oslo \"from Thread 2\" :true");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.debug: Oulu \"from Thread 2\" :true");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.debug: Berlin \"from Thread 2\" :true");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
|
||||
buf = QStringLiteral("Digia.Oslo.Office.com.debug: Oslo \"from Thread 2\" :false");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Oulu.Office.com.debug: Oulu \"from Thread 2\" :false");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
buf = QStringLiteral("Digia.Berlin.Office.com.debug: Berlin \"from Thread 2\" :false");
|
||||
compareagainst.append(cleanLogLine(buf));
|
||||
|
||||
for (int i = 0; i < threadtest.count(); i++) {
|
||||
if (!compareagainst.contains(cleanLogLine(threadtest[i]))){
|
||||
fprintf(stdout, "%s\r\n", threadtest[i].toLatin1().constData());
|
||||
QVERIFY2(false, "Multithread log is not complete!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cleanupTestCase()
|
||||
{
|
||||
delete _config;
|
||||
qInstallMessageHandler(oldMessageHandler);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_QLogging)
|
||||
|
||||
#include "tst_qloggingcategory.moc"
|
@ -49,6 +49,7 @@
|
||||
|
||||
#include <QtCore/QtCore>
|
||||
#include <QtCore/QtDebug>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class tst_QNoDebug: public QObject
|
||||
@ -61,12 +62,16 @@ private slots:
|
||||
|
||||
void tst_QNoDebug::noDebugOutput() const
|
||||
{
|
||||
QLoggingCategory cat("custom");
|
||||
// should do nothing
|
||||
qDebug() << "foo";
|
||||
qCDebug(cat) << "foo";
|
||||
|
||||
// qWarning still works, though
|
||||
QTest::ignoreMessage(QtWarningMsg, "bar ");
|
||||
QTest::ignoreMessage(QtWarningMsg, "custom-bar ");
|
||||
qWarning() << "bar";
|
||||
qCWarning(cat) << "custom-bar";
|
||||
}
|
||||
|
||||
void tst_QNoDebug::streaming() const
|
||||
|
Loading…
Reference in New Issue
Block a user