Allow configuration of logging rules from file system
Allow configuration of logging rules from outside of the application, either through a configuration file (.config/QtProject/qtlogging.ini), or through a file specified by a QT_LOGGING_CONF environment variable. The logging rules from the different sources are concatenated: First the rules from QtProject/qtlogging.ini are applied, then QLoggingCategory::setLoggingRules(), finally from the environment. This allows an application to overwrite/augment the system wide rules, and in turn that can be tailored for a specific run by setting a configuration in the environment variable. [ChangeLog][QtCore][Logging] The logging framework can now be configured with an .ini file. Change-Id: I442efde1b7e0a2ebe135c6f6e0a4b656483fe4b1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
dc09a02e3a
commit
a2bfd11493
@ -86,12 +86,62 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
|
|||||||
In the default configuration \l isWarningEnabled() , \l isDebugEnabled() and
|
In the default configuration \l isWarningEnabled() , \l isDebugEnabled() and
|
||||||
\l isCriticalEnabled() will return \c true.
|
\l isCriticalEnabled() will return \c true.
|
||||||
|
|
||||||
\section1 Changing the configuration of a category
|
\section1 Configuring Categories
|
||||||
|
|
||||||
Use either \l setFilterRules() or \l installFilter() to
|
Categories can be centrally configured by either setting logging rules,
|
||||||
configure categories, for example
|
or by installing a custom filter.
|
||||||
|
|
||||||
\snippet qloggingcategory/main.cpp 2
|
\section2 Logging Rules
|
||||||
|
|
||||||
|
Logging rules allow to enable or disable logging for categories in a flexible
|
||||||
|
way. Rules are specified in text, where every line must have the format
|
||||||
|
|
||||||
|
\code
|
||||||
|
<category>[.<type>] = true|false
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\c <category> is the name of the category, potentially with \c{*} as a
|
||||||
|
wildcard symbol as the first or last character (or at both positions).
|
||||||
|
The optional \c <type> must be either \c debug, \c warning, or \c critical.
|
||||||
|
Lines that do not fit to his scheme are ignored.
|
||||||
|
|
||||||
|
Rules are evaluated in text order, from first to last. That is, if two rules
|
||||||
|
apply to a category/type, the rule that comes later is applied.
|
||||||
|
|
||||||
|
Rules can be set via \l setFilterRules(). Since Qt 5.3 logging rules
|
||||||
|
are also automatically loaded from the \c [rules] section of a logging
|
||||||
|
configuration file. Such configuration files are looked up in the QtProject
|
||||||
|
configuration directory, or explicitly set in a \c QT_LOGGING_CONF
|
||||||
|
environment variable.
|
||||||
|
|
||||||
|
Rules set by \l setFilterRules() take precedence over rules specified
|
||||||
|
in the QtProject configuration directory, and can, in turn, be
|
||||||
|
overwritten by rules from the configuration file specified by
|
||||||
|
\c QT_LOGGING_CONF.
|
||||||
|
|
||||||
|
Order of evaluation:
|
||||||
|
\list
|
||||||
|
\li Rules from QtProject/qlogging.ini
|
||||||
|
\li Rules set by \l setFilterRules()
|
||||||
|
\li Rules from file in \c QT_LOGGING_CONF
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
The \c QtProject/qlogging.ini file is looked up in all directories returned
|
||||||
|
by QStandardPaths::GenericConfigLocation, e.g.
|
||||||
|
|
||||||
|
\list
|
||||||
|
\li on Mac OS X: \c ~/Library/Preferences
|
||||||
|
\li on Unix: \c ~/.config, \c /etc/xdg
|
||||||
|
\li on Windows: \c %LOCALAPPDATA%, \c %ProgramData%,
|
||||||
|
\l QCoreApplication::applicationDirPath(),
|
||||||
|
QCoreApplication::applicationDirPath() + \c "/data"
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\section2 Installing a Custom Filter
|
||||||
|
|
||||||
|
As a lower-level alternative to the text rules you can also implement a
|
||||||
|
custom filter via \l installFilter(). All filter rules are ignored in this
|
||||||
|
case.
|
||||||
|
|
||||||
\section1 Printing the category
|
\section1 Printing the category
|
||||||
|
|
||||||
@ -278,27 +328,18 @@ QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter)
|
|||||||
Configures which categories and message types should be enabled through a
|
Configures which categories and message types should be enabled through a
|
||||||
a set of \a rules.
|
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.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
\snippet qloggingcategory/main.cpp 2
|
\snippet qloggingcategory/main.cpp 2
|
||||||
|
|
||||||
\note The rules might be ignored if a custom category filter is installed
|
\note The rules might be ignored if a custom category filter is installed
|
||||||
with \l installFilter().
|
with \l installFilter(), or if the user defined a custom logging
|
||||||
|
configuration file in the \c QT_LOGGING_CONF environment variable.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void QLoggingCategory::setFilterRules(const QString &rules)
|
void QLoggingCategory::setFilterRules(const QString &rules)
|
||||||
{
|
{
|
||||||
QLoggingRegistry::instance()->rulesParser.setRules(rules);
|
QLoggingRegistry::instance()->setApiRules(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -42,6 +42,10 @@
|
|||||||
#include "qloggingregistry_p.h"
|
#include "qloggingregistry_p.h"
|
||||||
#include "qloggingcategory_p.h"
|
#include "qloggingcategory_p.h"
|
||||||
|
|
||||||
|
#include <QtCore/qfile.h>
|
||||||
|
#include <QtCore/qstandardpaths.h>
|
||||||
|
#include <QtCore/qtextstream.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(QLoggingRegistry, qtLoggingRegistry)
|
Q_GLOBAL_STATIC(QLoggingRegistry, qtLoggingRegistry)
|
||||||
@ -150,33 +154,38 @@ void QLoggingRule::parse()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
\class QLoggingSettingsParser
|
||||||
|
\since 5.3
|
||||||
\internal
|
\internal
|
||||||
Creates a new QLoggingRules object.
|
|
||||||
|
Parses a .ini file with the following format:
|
||||||
|
|
||||||
|
[rules]
|
||||||
|
rule1=[true|false]
|
||||||
|
rule2=[true|false]
|
||||||
|
...
|
||||||
|
|
||||||
|
[rules] is the default section, and therefore optional.
|
||||||
*/
|
*/
|
||||||
QLoggingRulesParser::QLoggingRulesParser(QLoggingRegistry *registry) :
|
|
||||||
registry(registry)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
Sets logging rules string.
|
Parses configuration from \a content.
|
||||||
*/
|
*/
|
||||||
void QLoggingRulesParser::setRules(const QString &content)
|
void QLoggingSettingsParser::setContent(const QString &content)
|
||||||
{
|
{
|
||||||
QString content_ = content;
|
QString content_ = content;
|
||||||
QTextStream stream(&content_, QIODevice::ReadOnly);
|
QTextStream stream(&content_, QIODevice::ReadOnly);
|
||||||
parseRules(stream);
|
setContent(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
Parses rules out of a QTextStream.
|
Parses configuration from \a stream.
|
||||||
*/
|
*/
|
||||||
void QLoggingRulesParser::parseRules(QTextStream &stream)
|
void QLoggingSettingsParser::setContent(QTextStream &stream)
|
||||||
{
|
{
|
||||||
QVector<QLoggingRule> rules;
|
_rules.clear();
|
||||||
|
|
||||||
while (!stream.atEnd()) {
|
while (!stream.atEnd()) {
|
||||||
QString line = stream.readLine();
|
QString line = stream.readLine();
|
||||||
|
|
||||||
@ -184,29 +193,77 @@ void QLoggingRulesParser::parseRules(QTextStream &stream)
|
|||||||
line = line.simplified();
|
line = line.simplified();
|
||||||
line.remove(QLatin1Char(' '));
|
line.remove(QLatin1Char(' '));
|
||||||
|
|
||||||
const QStringList pair = line.split(QLatin1Char('='));
|
// comment
|
||||||
if (pair.count() == 2) {
|
if (line.startsWith(QLatin1Char(';')))
|
||||||
const QString pattern = pair.at(0);
|
continue;
|
||||||
bool enabled = (QString::compare(pair.at(1),
|
|
||||||
QLatin1String("true"),
|
if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) {
|
||||||
Qt::CaseInsensitive) == 0);
|
// new section
|
||||||
rules.append(QLoggingRule(pattern, enabled));
|
_section = line.mid(1, line.size() - 2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_section == QLatin1String("rules")) {
|
||||||
|
int equalPos = line.indexOf(QLatin1Char('='));
|
||||||
|
if ((equalPos != -1)
|
||||||
|
&& (line.lastIndexOf(QLatin1Char('=')) == equalPos)) {
|
||||||
|
const QString pattern = line.left(equalPos);
|
||||||
|
const QStringRef value = line.midRef(equalPos + 1);
|
||||||
|
bool enabled = (value.compare(QLatin1String("true"),
|
||||||
|
Qt::CaseInsensitive) == 0);
|
||||||
|
_rules.append(QLoggingRule(pattern, enabled));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registry->setRules(rules);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
QLoggingPrivate constructor
|
QLoggingRegistry constructor
|
||||||
*/
|
*/
|
||||||
QLoggingRegistry::QLoggingRegistry()
|
QLoggingRegistry::QLoggingRegistry()
|
||||||
: rulesParser(this),
|
: categoryFilter(defaultCategoryFilter)
|
||||||
categoryFilter(defaultCategoryFilter)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Initializes the rules database by loading
|
||||||
|
.config/QtProject/qtlogging.ini and $QT_LOGGING_CONF.
|
||||||
|
*/
|
||||||
|
void QLoggingRegistry::init()
|
||||||
|
{
|
||||||
|
// get rules from environment
|
||||||
|
const QByteArray rulesFilePath = qgetenv("QT_LOGGING_CONF");
|
||||||
|
if (!rulesFilePath.isEmpty()) {
|
||||||
|
QFile file(QFile::decodeName(rulesFilePath));
|
||||||
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QTextStream stream(&file);
|
||||||
|
QLoggingSettingsParser parser;
|
||||||
|
parser.setContent(stream);
|
||||||
|
envRules = parser.rules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get rules from qt configuration
|
||||||
|
QString envPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation,
|
||||||
|
QStringLiteral("QtProject/qtlogging.ini"));
|
||||||
|
if (!envPath.isEmpty()) {
|
||||||
|
QFile file(envPath);
|
||||||
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
QTextStream stream(&file);
|
||||||
|
QLoggingSettingsParser parser;
|
||||||
|
parser.setContent(stream);
|
||||||
|
configRules = parser.rules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!envRules.isEmpty() || !configRules.isEmpty()) {
|
||||||
|
QMutexLocker locker(®istryMutex);
|
||||||
|
updateRules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
Registers a category object.
|
Registers a category object.
|
||||||
@ -236,17 +293,33 @@ void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat)
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
Activates a new set of logging rules for the default filter.
|
Installs logging rules as specified in \a content.
|
||||||
*/
|
*/
|
||||||
void QLoggingRegistry::setRules(const QVector<QLoggingRule> &rules_)
|
void QLoggingRegistry::setApiRules(const QString &content)
|
||||||
{
|
{
|
||||||
|
QLoggingSettingsParser parser;
|
||||||
|
parser.setSection(QStringLiteral("rules"));
|
||||||
|
parser.setContent(content);
|
||||||
|
|
||||||
QMutexLocker locker(®istryMutex);
|
QMutexLocker locker(®istryMutex);
|
||||||
|
apiRules = parser.rules();
|
||||||
|
|
||||||
rules = rules_;
|
updateRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Activates a new set of logging rules for the default filter.
|
||||||
|
|
||||||
|
(The caller must lock registryMutex to make sure the API is thread safe.)
|
||||||
|
*/
|
||||||
|
void QLoggingRegistry::updateRules()
|
||||||
|
{
|
||||||
if (categoryFilter != defaultCategoryFilter)
|
if (categoryFilter != defaultCategoryFilter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
rules = configRules + apiRules + envRules;
|
||||||
|
|
||||||
foreach (QLoggingCategory *cat, categories)
|
foreach (QLoggingCategory *cat, categories)
|
||||||
(*categoryFilter)(cat);
|
(*categoryFilter)(cat);
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,8 @@
|
|||||||
#include <QtCore/qtextstream.h>
|
#include <QtCore/qtextstream.h>
|
||||||
#include <QtCore/qvector.h>
|
#include <QtCore/qvector.h>
|
||||||
|
|
||||||
|
class tst_QLoggingRegistry;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QLoggingRule
|
class QLoggingRule
|
||||||
@ -89,45 +91,53 @@ private:
|
|||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags)
|
||||||
Q_DECLARE_TYPEINFO(QLoggingRule, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(QLoggingRule, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
class QLoggingRulesParser
|
class Q_AUTOTEST_EXPORT QLoggingSettingsParser
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
explicit QLoggingRulesParser(class QLoggingRegistry *logging);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setRules(const QString &content);
|
void setSection(const QString §ion) { _section = section; }
|
||||||
|
|
||||||
|
void setContent(const QString &content);
|
||||||
|
void setContent(QTextStream &stream);
|
||||||
|
|
||||||
|
QVector<QLoggingRule> rules() const { return _rules; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parseRules(QTextStream &stream);
|
QString _section;
|
||||||
QLoggingRegistry *registry;
|
QVector<QLoggingRule> _rules;
|
||||||
|
|
||||||
friend class QLoggingRegistry;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QLoggingRegistry
|
class Q_AUTOTEST_EXPORT QLoggingRegistry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QLoggingRegistry();
|
QLoggingRegistry();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
void registerCategory(QLoggingCategory *category);
|
void registerCategory(QLoggingCategory *category);
|
||||||
void unregisterCategory(QLoggingCategory *category);
|
void unregisterCategory(QLoggingCategory *category);
|
||||||
|
|
||||||
void setRules(const QVector<QLoggingRule> &rules);
|
void setApiRules(const QString &content);
|
||||||
|
|
||||||
QLoggingCategory::CategoryFilter
|
QLoggingCategory::CategoryFilter
|
||||||
installFilter(QLoggingCategory::CategoryFilter filter);
|
installFilter(QLoggingCategory::CategoryFilter filter);
|
||||||
|
|
||||||
static QLoggingRegistry *instance();
|
static QLoggingRegistry *instance();
|
||||||
|
|
||||||
QLoggingRulesParser rulesParser;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateRules();
|
||||||
|
|
||||||
static void defaultCategoryFilter(QLoggingCategory *category);
|
static void defaultCategoryFilter(QLoggingCategory *category);
|
||||||
|
|
||||||
QMutex registryMutex;
|
QMutex registryMutex;
|
||||||
|
|
||||||
|
QVector<QLoggingRule> configRules;
|
||||||
|
QVector<QLoggingRule> envRules;
|
||||||
|
QVector<QLoggingRule> apiRules;
|
||||||
QVector<QLoggingRule> rules;
|
QVector<QLoggingRule> rules;
|
||||||
QList<QLoggingCategory*> categories;
|
QList<QLoggingCategory*> categories;
|
||||||
QLoggingCategory::CategoryFilter categoryFilter;
|
QLoggingCategory::CategoryFilter categoryFilter;
|
||||||
|
|
||||||
|
friend class ::tst_QLoggingRegistry;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include <qfileinfo.h>
|
#include <qfileinfo.h>
|
||||||
#include <qhash.h>
|
#include <qhash.h>
|
||||||
#include <qmutex.h>
|
#include <qmutex.h>
|
||||||
|
#include <private/qloggingregistry_p.h>
|
||||||
#include <private/qprocess_p.h>
|
#include <private/qprocess_p.h>
|
||||||
#include <qstandardpaths.h>
|
#include <qstandardpaths.h>
|
||||||
#include <qtextcodec.h>
|
#include <qtextcodec.h>
|
||||||
@ -722,6 +723,10 @@ void QCoreApplication::init()
|
|||||||
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
|
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
|
||||||
QCoreApplication::self = this;
|
QCoreApplication::self = this;
|
||||||
|
|
||||||
|
#ifndef QT_BOOTSTRAPPED
|
||||||
|
QLoggingRegistry::instance()->init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
// use the event dispatcher created by the app programmer (if any)
|
// use the event dispatcher created by the app programmer (if any)
|
||||||
if (!QCoreApplicationPrivate::eventDispatcher)
|
if (!QCoreApplicationPrivate::eventDispatcher)
|
||||||
|
@ -17,6 +17,7 @@ SUBDIRS=\
|
|||||||
qipaddress \
|
qipaddress \
|
||||||
qlockfile \
|
qlockfile \
|
||||||
qloggingcategory \
|
qloggingcategory \
|
||||||
|
qloggingregistry \
|
||||||
qnodebug \
|
qnodebug \
|
||||||
qprocess \
|
qprocess \
|
||||||
qprocess-noapplication \
|
qprocess-noapplication \
|
||||||
@ -51,7 +52,8 @@ SUBDIRS=\
|
|||||||
qabstractfileengine \
|
qabstractfileengine \
|
||||||
qfileinfo \
|
qfileinfo \
|
||||||
qipaddress \
|
qipaddress \
|
||||||
qurlinternal
|
qurlinternal \
|
||||||
|
qloggingregistry
|
||||||
|
|
||||||
win32:!contains(QT_CONFIG, private_tests): SUBDIRS -= \
|
win32:!contains(QT_CONFIG, private_tests): SUBDIRS -= \
|
||||||
qfilesystementry
|
qfilesystementry
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
TEMPLATE = app
|
||||||
|
TARGET = tst_qloggingregistry
|
||||||
|
|
||||||
|
CONFIG += testcase
|
||||||
|
QT = core core-private testlib
|
||||||
|
|
||||||
|
SOURCES += tst_qloggingregistry.cpp
|
||||||
|
OTHER_FILES += qtlogging.ini
|
2
tests/auto/corelib/io/qloggingregistry/qtlogging.ini
Normal file
2
tests/auto/corelib/io/qloggingregistry/qtlogging.ini
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[rules]
|
||||||
|
*=true
|
179
tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
Normal file
179
tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 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 <QLoggingCategory>
|
||||||
|
|
||||||
|
#include <QtCore/private/qloggingregistry_p.h>
|
||||||
|
|
||||||
|
QT_USE_NAMESPACE
|
||||||
|
|
||||||
|
class tst_QLoggingRegistry : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void initTestCase()
|
||||||
|
{
|
||||||
|
// ensure a clean environment
|
||||||
|
QStandardPaths::setTestModeEnabled(true);
|
||||||
|
qunsetenv("QT_LOGGING_CONF");
|
||||||
|
}
|
||||||
|
|
||||||
|
void QLoggingSettingsParser_iniStyle()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Logging configuration can be described
|
||||||
|
// in an .ini file. [rules] is the
|
||||||
|
// default category, and optional ...
|
||||||
|
//
|
||||||
|
QLoggingSettingsParser parser;
|
||||||
|
parser.setContent("[rules]\n"
|
||||||
|
"default=false\n"
|
||||||
|
"default=true");
|
||||||
|
QCOMPARE(parser.rules().size(), 2);
|
||||||
|
|
||||||
|
parser.setContent("[rules]\n"
|
||||||
|
"default=false");
|
||||||
|
QCOMPARE(parser.rules().size(), 1);
|
||||||
|
|
||||||
|
parser.setContent("[OtherSection]\n"
|
||||||
|
"default=false");
|
||||||
|
QCOMPARE(parser.rules().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QLoggingRegistry_environment()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Check whether QT_LOGGING_CONF is picked up from environment
|
||||||
|
//
|
||||||
|
|
||||||
|
qputenv("QT_LOGGING_CONF", QFINDTESTDATA("qtlogging.ini").toLocal8Bit());
|
||||||
|
|
||||||
|
QLoggingRegistry registry;
|
||||||
|
registry.init();
|
||||||
|
|
||||||
|
QCOMPARE(registry.apiRules.size(), 0);
|
||||||
|
QCOMPARE(registry.configRules.size(), 0);
|
||||||
|
QCOMPARE(registry.envRules.size(), 1);
|
||||||
|
|
||||||
|
QCOMPARE(registry.rules.size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QLoggingRegistry_config()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Check whether QtProject/qtlogging.ini is loaded automatically
|
||||||
|
//
|
||||||
|
|
||||||
|
// first try to create a test file..
|
||||||
|
QString path = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
|
||||||
|
QVERIFY(!path.isEmpty());
|
||||||
|
QDir dir(path + "/QtProject");
|
||||||
|
if (!dir.exists())
|
||||||
|
QVERIFY(dir.mkpath(path + "/QtProject"));
|
||||||
|
|
||||||
|
QFile file(dir.absoluteFilePath("qtlogging.ini"));
|
||||||
|
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
|
||||||
|
QTextStream out(&file);
|
||||||
|
out << "[rules]\n";
|
||||||
|
out << "Digia.*=false\n";
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
QLoggingRegistry registry;
|
||||||
|
registry.init();
|
||||||
|
QCOMPARE(registry.configRules.size(), 1);
|
||||||
|
|
||||||
|
// remove file again
|
||||||
|
QVERIFY(file.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QLoggingRegistry_rulePriorities()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Rules can stem from 3 sources:
|
||||||
|
// via QLoggingCategory::setFilterRules (API)
|
||||||
|
// via qtlogging.ini file in settings (Config)
|
||||||
|
// via QT_LOGGING_CONF environment variable (Env)
|
||||||
|
//
|
||||||
|
// Rules set by environment should get higher precedence than qtlogging.conf,
|
||||||
|
// than QLoggingCategory::setFilterRules
|
||||||
|
//
|
||||||
|
|
||||||
|
QLoggingCategory cat("Digia.Berlin");
|
||||||
|
QLoggingRegistry *registry = QLoggingRegistry::instance();
|
||||||
|
|
||||||
|
// empty all rules , check default
|
||||||
|
registry->rules.clear();
|
||||||
|
registry->apiRules.clear();
|
||||||
|
registry->configRules.clear();
|
||||||
|
registry->envRules.clear();
|
||||||
|
registry->updateRules();
|
||||||
|
|
||||||
|
QVERIFY(cat.isWarningEnabled());
|
||||||
|
|
||||||
|
// set Config rule
|
||||||
|
QLoggingSettingsParser parser;
|
||||||
|
parser.setContent("[rules]\nDigia.*=false");
|
||||||
|
registry->configRules=parser.rules();
|
||||||
|
registry->updateRules();
|
||||||
|
|
||||||
|
QVERIFY(!cat.isWarningEnabled());
|
||||||
|
|
||||||
|
// set API rule, should overwrite API one
|
||||||
|
QLoggingCategory::setFilterRules("Digia.*=true");
|
||||||
|
|
||||||
|
QVERIFY(cat.isWarningEnabled());
|
||||||
|
|
||||||
|
// set Env rule, should overwrite Config one
|
||||||
|
parser.setContent("Digia.*=false");
|
||||||
|
registry->envRules=parser.rules();
|
||||||
|
registry->updateRules();
|
||||||
|
|
||||||
|
QVERIFY(!cat.isWarningEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_QLoggingRegistry)
|
||||||
|
|
||||||
|
#include "tst_qloggingregistry.moc"
|
Loading…
x
Reference in New Issue
Block a user