SVN commit 1204637 by dfaure: Further fixes to kDebug: * Since KConfig works without a main componentdata nowadays (auto-created by kglobal), make kDebug work pretty much the same in qt-only apps as in kde apps, including obeying kdebugrc settings. The only difference is that area 0 (and unknown areas) are called qAppName() rather than main-component-data-name. * Update that name when the main component data gets created, even after early kDebugs. * Make the handling of unknown numbered areas more consistent (using the settings for area 0) * Complete unittest for the "no component data" case, in a separate program called by kdebug_unittest. CCMAIL: mpyne@kde.org M +26 -23 io/kdebug.cpp M +1 -0 tests/CMakeLists.txt A tests/kdebug_qcoreapptest.cpp [License: LGPL (v2+)] M +43 -5 tests/kdebug_unittest.cpp M +1 -0 tests/kdebug_unittest.h M +0 -4 tests/qcoreapptest.cpp --- trunk/KDE/kdelibs/kdecore/io/kdebug.cpp #1204636:1204637 @@ -217,7 +217,7 @@ typedef QHash Cache; KDebugPrivate() - : config(0), kDebugDBusIface(0), m_disableAll(false) + : config(0), kDebugDBusIface(0), m_disableAll(false), m_seenMainComponent(false) { Q_ASSERT(int(QtDebugMsg) == 0); Q_ASSERT(int(QtFatalMsg) == 3); @@ -252,14 +252,20 @@ void loadAreaNames() { - cache.clear(); + // Don't clear the cache here, that would lose previously registered dynamic areas + //cache.clear(); Area &areaData = cache[0]; areaData.clear(); - Q_ASSERT(KGlobal::hasMainComponent()); + if (KGlobal::hasMainComponent()) { areaData.name = KGlobal::mainComponent().componentName().toUtf8(); - //qDebug() << "loadAreaNames: area 0 has name" << KGlobal::mainComponent().componentName().toUtf8(); + m_seenMainComponent = true; + } else { + areaData.name = qApp ? qAppName().toUtf8() : QByteArray("unnamed app"); + m_seenMainComponent = false; + } + //qDebug() << "loadAreaNames: area 0 has name" << areaData.name; for (int i = 0; i < 8; i++) { m_nullOutputYesNoCache[i] = -1; @@ -325,7 +331,7 @@ OutputMode areaOutputMode(QtMsgType type, unsigned int area, bool enableByDefault) { - if (!config) + if (!configObject()) return QtOutput; QString key; @@ -355,7 +361,7 @@ QString logFileName(QtMsgType type, unsigned int area) { - if (!config) + if (!configObject()) return QString(); const char* aKey; @@ -391,30 +397,22 @@ Cache::Iterator areaData(QtMsgType type, unsigned int num, bool enableByDefault = true) { - if (!configObject() || !KGlobal::hasMainComponent()) { - // we don't have a config and we can't create one... - // or we don't have a main component (yet?) - Area &area = cache[0]; // create a dummy entry - if (area.name.isEmpty()) { - if (KGlobal::hasMainComponent()) - area.name = KGlobal::mainComponent().componentName().toUtf8(); - else - area.name = qApp ? qAppName().toUtf8() : QByteArray("unnamed app"); - } - //qDebug() << "Created dummy entry for area 0 with name" << area.name; - return cache.find(0); - } - - if (!cache.contains(0) || (cache.count() == 1 && KGlobal::hasMainComponent())) { + if (!cache.contains(0)) { //qDebug() << "cache size=" << cache.count() << "loading area names"; loadAreaNames(); // fills 'cache' + Q_ASSERT(cache.contains(0)); + } else if (!m_seenMainComponent && KGlobal::hasMainComponent()) { + // Update the name for area 0 once a main component exists + cache[0].name = KGlobal::mainComponent().componentName().toUtf8(); + m_seenMainComponent = true; } Cache::Iterator it = cache.find(num); if (it == cache.end()) { // unknown area Q_ASSERT(cache.contains(0)); - return cache.find(0); + it = cache.find(0); + num = 0; } if (num == 0 && type == QtDebugMsg) { // area 0 is special, it becomes the named area "appname" @@ -433,6 +431,8 @@ if (it->mode[lev] == FileOutput && it->logFileName[lev].isEmpty()) it->logFileName[lev] = logFileName(type, num); + Q_ASSERT(it->mode[lev] != Unknown); + return it; } @@ -630,6 +630,7 @@ static bool env_colored = (!qgetenv("KDE_COLOR_DEBUG").isEmpty()); Cache::Iterator it = areaData(type, area); OutputMode mode = it->mode[level(type)]; + Q_ASSERT(mode != Unknown); QString file = it->logFileName[level(type)]; QByteArray areaName = it->name; @@ -649,11 +650,11 @@ case SyslogOutput: s = setupSyslogWriter(type); break; - case Unknown: // don't want kdelibs debug output in Qt-only programs with no componentdata (-> no kdebugrc) case NoOutput: s = QDebug(&devnull); return s; //no need to take the time to "print header" if we don't want to output anyway break; + case Unknown: // should not happen default: // QtOutput s = setupQtWriter(type); #ifndef Q_OS_WIN @@ -686,6 +687,7 @@ KDebugDBusIface *kDebugDBusIface; Cache cache; bool m_disableAll; + bool m_seenMainComponent; // false: area zero still contains qAppName int m_nullOutputYesNoCache[8]; KNoDebugStream devnull; @@ -861,6 +863,7 @@ } KDebugPrivate::Area areaData; areaData.name = areaName; + //qDebug() << "Assigning area number" << areaNumber << "for name" << areaName; d->cache.insert(areaNumber, areaData); d->writeGroupForNamedArea(areaName, enabled); return areaNumber; --- trunk/KDE/kdelibs/kdecore/tests/CMakeLists.txt #1204636:1204637 @@ -68,6 +68,7 @@ kdebug_unittest kencodingdetectortest qcoreapptest + kdebug_qcoreapptest ) if(NOT KDE_NO_DEPRECATED) --- trunk/KDE/kdelibs/kdecore/tests/kdebug_unittest.cpp #1204636:1204637 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "kdebug_unittest.moc" @@ -45,9 +46,11 @@ config.group("qttest").writeEntry("WarnOutput", 0 /*FileOutput*/); config.sync(); + //QCOMPARE(KDebug::hasNullOutput(QtDebugMsg, true, 0, false), false); + // Test for crash that used to happen when using an unknown area after only dynamic areas - KDebug::registerArea("somearea"); - KDebug::registerArea("someotherarea"); + KDebug::registerArea("somearea"); // gets number 1 + KDebug::registerArea("someotherarea"); // gets number 2 QCOMPARE(KDebug::hasNullOutput(QtDebugMsg, true, 4242, false), false); // unknown area -> area 0 is being used kClearDebugConfig(); @@ -179,14 +182,14 @@ void KDebugTest::testDynamicArea() { - const int myArea = KDebug::registerArea("myarea"); - QVERIFY(myArea > 0); + const int myArea = KDebug::registerArea("myarea"); // gets number 3 + QCOMPARE(myArea, 3); KConfig config("kdebugrc"); QVERIFY(!config.hasGroup(QString::number(myArea))); QVERIFY(config.hasGroup("myarea")); kDebug(myArea) << "TEST DEBUG using myArea" << myArea; QList expected; - expected << "/myarea KDebugTest::testDynamicArea: TEST DEBUG using myArea 1\n"; + expected << "/myarea KDebugTest::testDynamicArea: TEST DEBUG using myArea 3\n"; compareLines(expected, "myarea.dbg"); } @@ -252,6 +255,41 @@ kClearDebugConfig(); } +void KDebugTest::testNoMainComponentData() +{ + // This test runs kdebug_qcoreapptest and checks its output + KProcess proc; + proc.setEnv("KDE_DEBUG_NOPROCESSINFO", "1"); + proc.setOutputChannelMode(KProcess::OnlyStderrChannel); +#ifdef Q_OS_WIN + proc << "kdebug_qcoreapptest.exe"; +#else + if (QFile::exists("./kdebug_qcoreapptest.shell")) + proc << "./kdebug_qcoreapptest.shell"; + else { + QVERIFY(QFile::exists("./kdebug_qcoreapptest")); + proc << "./kdebug_qcoreapptest"; + } +#endif + // kDebug() << proc.args(); + const int ok = proc.execute(); + QVERIFY(ok == 0); + const QByteArray allOutput = proc.readAllStandardError(); + const QList receivedLines = allOutput.split('\n'); + //qDebug() << receivedLines; + QList expectedLines; + expectedLines << "qcoreapp_myarea main: Test debug using qcoreapp_myarea 1"; + expectedLines << "kdebug_qcoreapptest main: Debug in area 100"; + expectedLines << "kdebug_qcoreapptest main: Simple debug"; + expectedLines << "kdebug_qcoreapptest_mainData main: This should appear, under the kdebug_qcoreapptest_mainData area"; + expectedLines << "kdebug_qcoreapptest_mainData main: Debug in area 100"; + expectedLines << ""; // artefact of split, I guess? + for (int i = 0; i < qMin(expectedLines.count(), receivedLines.count()); ++i) + QCOMPARE(QString::fromLatin1(receivedLines[i]), QString::fromLatin1(expectedLines[i])); + QCOMPARE(receivedLines.count(), expectedLines.count()); + QCOMPARE(receivedLines, expectedLines); +} + #include #include --- trunk/KDE/kdelibs/kdecore/tests/kdebug_unittest.h #1204636:1204637 @@ -37,6 +37,7 @@ void testDisabledDynamicArea(); void testDisableAll(); void testHasNullOutput(); + void testNoMainComponentData(); void testMultipleThreads(); private: --- trunk/KDE/kdelibs/kdecore/tests/qcoreapptest.cpp #1204636:1204637 @@ -36,10 +36,6 @@ const QString ok = i18n("OK"); Q_UNUSED(ok); - // Test that KDebug works - kDebug() << "This should appear, but disabling qcoreapptest in kdebugdialog should make it go away."; - // TODO automate the above test, see kdebug_unittest.cpp - return 0; }