Quick tests: Introduce QQmlMessageHandler.
authorFriedemann Kleint <Friedemann.Kleint@digia.com>
Tue, 18 Dec 2012 10:41:06 +0000 (11:41 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 20 Dec 2012 20:38:38 +0000 (21:38 +0100)
Add QQmlMessageHandler class that can be used to record messages
into a QStringList. It also makes sure that the old message
handler is reinstalled if the test fails.

Task-number: QTBUG-28611
Change-Id: I0fff7bc11e188cf47178d9573e5f2eead693bc10
Reviewed-by: Kai Koehne <kai.koehne@digia.com>

14 files changed:
tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
tests/auto/qml/qqmlinstruction/qqmlinstruction.pro
tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
tests/auto/qml/qqmlpropertymap/qqmlpropertymap.pro
tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
tests/auto/qml/v4/tst_v4.cpp
tests/auto/quick/qquickimage/tst_qquickimage.cpp
tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
tests/auto/quick/qquickview/tst_qquickview.cpp
tests/auto/shared/util.cpp
tests/auto/shared/util.h

index d3aba44..748d4d7 100644 (file)
@@ -226,20 +226,13 @@ void tst_qqmlcomponent::qmlCreateObjectWithProperties()
     delete testBindingThisObj;
 }
 
-static QStringList warnings;
-static void msgHandler(QtMsgType, const QMessageLogContext &, const QString &warning)
-{
-    warnings << warning;
-}
-
 void tst_qqmlcomponent::qmlCreateParentReference()
 {
     QQmlEngine engine;
 
     QCOMPARE(engine.outputWarningsToStandardError(), true);
 
-    warnings.clear();
-    QtMessageHandler old = qInstallMessageHandler(msgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QQmlComponent component(&engine, testFileUrl("createParentReference.qml"));
     QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
@@ -249,12 +242,10 @@ void tst_qqmlcomponent::qmlCreateParentReference()
     QVERIFY(QMetaObject::invokeMethod(object, "createChild"));
     delete object;
 
-    qInstallMessageHandler(old);
-
     engine.setOutputWarningsToStandardError(false);
     QCOMPARE(engine.outputWarningsToStandardError(), false);
 
-    QCOMPARE(warnings.count(), 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 }
 
 void tst_qqmlcomponent::async()
@@ -398,13 +389,14 @@ void tst_qqmlcomponent::onDestructionCount()
     // Warning should not be emitted any further
     QCOMPARE(engine.outputWarningsToStandardError(), true);
 
-    warnings.clear();
-    QtMessageHandler old = qInstallMessageHandler(msgHandler);
-
-    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
-    QCoreApplication::processEvents();
+    QStringList warnings;
+    {
+        QQmlTestMessageHandler messageHandler;
 
-    qInstallMessageHandler(old);
+        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+        QCoreApplication::processEvents();
+        warnings = messageHandler.messages();
+    }
 
     engine.setOutputWarningsToStandardError(false);
     QCOMPARE(engine.outputWarningsToStandardError(), false);
index bca76a7..9ecb3b6 100644 (file)
@@ -1923,27 +1923,18 @@ void tst_qqmlecmascript::compileInvalidBinding()
     delete object;
 }
 
-static int transientErrorsMsgCount = 0;
-static void transientErrorsMsgHandler(QtMsgType, const QMessageLogContext &, const QString &)
-{
-    ++transientErrorsMsgCount;
-}
-
 // Check that transient binding errors are not displayed
 void tst_qqmlecmascript::transientErrors()
 {
     {
     QQmlComponent component(&engine, testFileUrl("transientErrors.qml"));
 
-    transientErrorsMsgCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(transientErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QObject *object = component.create();
     QVERIFY(object != 0);
 
-    qInstallMessageHandler(old);
-
-    QCOMPARE(transientErrorsMsgCount, 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 
     delete object;
     }
@@ -1952,15 +1943,12 @@ void tst_qqmlecmascript::transientErrors()
     {
     QQmlComponent component(&engine, testFileUrl("transientErrors.2.qml"));
 
-    transientErrorsMsgCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(transientErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QObject *object = component.create();
     QVERIFY(object != 0);
 
-    qInstallMessageHandler(old);
-
-    QCOMPARE(transientErrorsMsgCount, 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 
     delete object;
     }
@@ -1973,13 +1961,11 @@ void tst_qqmlecmascript::shutdownErrors()
     QObject *object = component.create();
     QVERIFY(object != 0);
 
-    transientErrorsMsgCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(transientErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     delete object;
 
-    qInstallMessageHandler(old);
-    QCOMPARE(transientErrorsMsgCount, 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 }
 
 void tst_qqmlecmascript::compositePropertyType()
@@ -5794,14 +5780,11 @@ void tst_qqmlecmascript::qtbug_9792()
 
     delete context;
 
-    transientErrorsMsgCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(transientErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     object->basicSignal();
-    
-    qInstallMessageHandler(old);
 
-    QCOMPARE(transientErrorsMsgCount, 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 
     delete object;
 }
@@ -5835,14 +5818,11 @@ void tst_qqmlecmascript::noSpuriousWarningsAtShutdown()
 
     QObject *o = component.create();
 
-    transientErrorsMsgCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(transientErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     delete o;
 
-    qInstallMessageHandler(old);
-
-    QCOMPARE(transientErrorsMsgCount, 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     }
 
 
@@ -5851,14 +5831,11 @@ void tst_qqmlecmascript::noSpuriousWarningsAtShutdown()
 
     QObject *o = component.create();
 
-    transientErrorsMsgCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(transientErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     delete o;
 
-    qInstallMessageHandler(old);
-
-    QCOMPARE(transientErrorsMsgCount, 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     }
 }
 
@@ -6672,22 +6649,15 @@ void tst_qqmlecmascript::doubleEvaluate()
     delete object;
 }
 
-static QStringList messages;
-static void captureMsgHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
-{
-    messages.append(msg);
-}
-
 void tst_qqmlecmascript::nonNotifyable()
 {
     QV4Compiler::enableV4(false);
     QQmlComponent component(&engine, testFileUrl("nonNotifyable.qml"));
     QV4Compiler::enableV4(true);
 
-    QtMessageHandler old = qInstallMessageHandler(captureMsgHandler);
-    messages.clear();
+    QQmlTestMessageHandler messageHandler;
+
     QObject *object = component.create();
-    qInstallMessageHandler(old);
 
     QVERIFY(object != 0);
 
@@ -6698,9 +6668,9 @@ void tst_qqmlecmascript::nonNotifyable()
                         QLatin1String(object->metaObject()->className()) +
                         QLatin1String("::value");
 
-    QCOMPARE(messages.length(), 2);
-    QCOMPARE(messages.at(0), expected1);
-    QCOMPARE(messages.at(1), expected2);
+    QCOMPARE(messageHandler.messages().length(), 2);
+    QCOMPARE(messageHandler.messages().at(0), expected1);
+    QCOMPARE(messageHandler.messages().at(1), expected2);
 
     delete object;
 }
@@ -7125,16 +7095,14 @@ void tst_qqmlecmascript::bindingSuppression()
     EventProcessor processor;
     engine.rootContext()->setContextProperty("pendingEvents", &processor);
 
-    transientErrorsMsgCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(transientErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QQmlComponent c(&engine, testFileUrl("bindingSuppression.qml"));
     QObject *obj = c.create();
     QVERIFY(obj != 0);
     delete obj;
 
-    qInstallMessageHandler(old);
-    QCOMPARE(transientErrorsMsgCount, 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 }
 
 void tst_qqmlecmascript::signalEmitted()
index 128294b..2a78831 100644 (file)
@@ -417,12 +417,6 @@ void tst_qqmlengine::failedCompilation_data()
     QTest::newRow("Invalid content") << "failedCompilation.1.qml";
 }
 
-static QStringList warnings;
-static void msgHandler(QtMsgType, const QMessageLogContext &, const QString &warning)
-{
-    warnings << warning;
-}
-
 void tst_qqmlengine::outputWarningsToStandardError()
 {
     QQmlEngine engine;
@@ -434,35 +428,26 @@ void tst_qqmlengine::outputWarningsToStandardError()
 
     QVERIFY(c.isReady() == true);
 
-    warnings.clear();
-    QtMessageHandler old = qInstallMessageHandler(msgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QObject *o = c.create();
 
-    qInstallMessageHandler(old);
-
     QVERIFY(o != 0);
     delete o;
 
-    QCOMPARE(warnings.count(), 1);
-    QCOMPARE(warnings.at(0), QLatin1String("<Unknown File>: Unable to assign [undefined] to int"));
-    warnings.clear();
-
+    QCOMPARE(messageHandler.messages().count(), 1);
+    QCOMPARE(messageHandler.messages().at(0), QLatin1String("<Unknown File>: Unable to assign [undefined] to int"));
+    messageHandler.clear();
 
     engine.setOutputWarningsToStandardError(false);
     QCOMPARE(engine.outputWarningsToStandardError(), false);
 
-
-    old = qInstallMessageHandler(msgHandler);
-
     o = c.create();
 
-    qInstallMessageHandler(old);
-
     QVERIFY(o != 0);
     delete o;
 
-    QCOMPARE(warnings.count(), 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 }
 
 void tst_qqmlengine::objectOwnership()
index 1eb4a20..73f29ab 100644 (file)
@@ -5,5 +5,7 @@ macx:CONFIG -= app_bundle
 
 CONFIG += parallel_test
 
+include (../../shared/util.pri)
+
 QT += core-private gui-private v8-private qml-private testlib
 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
index 591d472..e25c38d 100644 (file)
@@ -40,6 +40,7 @@
 ****************************************************************************/
 
 #include <qtest.h>
+#include "../../shared/util.h"
 #include <private/qqmlcompiler_p.h>
 
 #include <QVector3D>
@@ -65,12 +66,6 @@ private slots:
     void time();
 };
 
-static QStringList messages;
-static void msgHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
-{
-    messages << msg;
-}
-
 void tst_qqmlinstruction::dump()
 {
     QQmlEngine engine;
@@ -564,15 +559,14 @@ void tst_qqmlinstruction::dump()
         << "57\t\tSTORE_VAR_BOOL\t\t83\ttrue"
         << "-------------------------------------------------------------------------------";
 
-    messages = QStringList();
-    QtMessageHandler old = qInstallMessageHandler(msgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     data->dumpInstructions();
-    qInstallMessageHandler(old);
 
-    QCOMPARE(messages.count(), expect.count());
-    for (int ii = 0; ii < messages.count(); ++ii) {
-        QCOMPARE(messages.at(ii), expect.at(ii));
+    const int messageCount = messageHandler.messages().count();
+    QCOMPARE(messageCount, expect.count());
+    for (int ii = 0; ii < messageCount; ++ii) {
+        QCOMPARE(messageHandler.messages().at(ii), expect.at(ii));
     }
 
     data->release();
index bf22afa..81212bb 100644 (file)
@@ -4,6 +4,8 @@ macx:CONFIG -= app_bundle
 
 SOURCES += tst_qqmlpropertymap.cpp
 
+include (../../shared/util.pri)
+
 CONFIG += parallel_test
 
 QT += core-private gui-private qml-private quick-private testlib
index 99179f5..af2a032 100644 (file)
@@ -39,6 +39,7 @@
 **
 ****************************************************************************/
 #include <qtest.h>
+#include "../../shared/util.h"
 #include <QtQml/qqmlengine.h>
 #include <QtQml/qqmlcontext.h>
 #include <QtQml/qqmlpropertymap.h>
@@ -294,19 +295,9 @@ public slots:
     void testSlot() {}
 };
 
-namespace
-{
-    QStringList messages;
-    void msgHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
-    {
-        messages << msg;
-    }
-}
-
 void tst_QQmlPropertyMap::metaObjectAccessibility()
 {
-    messages.clear();
-    QtMessageHandler old = qInstallMessageHandler(msgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QQmlEngine engine;
 
@@ -318,9 +309,7 @@ void tst_QQmlPropertyMap::metaObjectAccessibility()
 
     QCOMPARE(map.metaObject()->className(), "MyEnhancedPropertyMap");
 
-    qInstallMessageHandler(old);
-
-    QCOMPARE(messages.count(), 0);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 }
 
 QTEST_MAIN(tst_QQmlPropertyMap)
index f5e66a1..0644b36 100644 (file)
@@ -104,16 +104,6 @@ void tst_v4::initTestCase()
     registerTypes();
 }
 
-static int v4ErrorCount;
-static QList<QString> v4ErrorMessages;
-static void v4ErrorsMsgHandler(QtMsgType, const QMessageLogContext &, const QString &message)
-{
-    v4ErrorMessages.append(message);
-
-    if (message.contains("QV4"))
-        ++v4ErrorCount;
-}
-
 void tst_v4::qtscript()
 {
     QFETCH(QString, file);
@@ -121,21 +111,14 @@ void tst_v4::qtscript()
 
     QQmlComponent component(&engine, testFileUrl(file));
 
-    v4ErrorCount = 0;
-    v4ErrorMessages.clear();
-    QtMessageHandler old = qInstallMessageHandler(v4ErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QObject *o = component.create();
     delete o;
 
-    qInstallMessageHandler(old);
-
-    if (v4ErrorCount) {
-        foreach (const QString &msg, v4ErrorMessages)
-            qDebug() << msg;
-    }
     QEXPECT_FAIL("jsvalueHandling", "QTBUG-26951 - QJSValue has a different representation of NULL to QV8Engine", Continue);
-    QCOMPARE(v4ErrorCount, 0);
+    const int v4ErrorCount = messageHandler.messages().filter(QLatin1String("QV4")).size();
+    QVERIFY2(v4ErrorCount == 0, qPrintable(messageHandler.messageString()));
 
     QV4Compiler::enableBindingsTest(false);
 }
@@ -959,12 +942,6 @@ void tst_v4::subscriptions()
     }
 }
 
-static QStringList messages;
-static void msgHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
-{
-    messages << msg;
-}
-
 static QByteArray getAddress(int address)
 {
     return QByteArray::number(address);
@@ -1108,8 +1085,7 @@ void tst_v4::debuggingDumpInstructions()
     expectedPreAddress << "\t\tInitString\t\tString_DataIndex(0) -> String_Slot(0)";
     QStringList expected;
 
-    messages = QStringList();
-    QtMessageHandler old = qInstallMessageHandler(msgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     QQmlJS::Bytecode bc;
 #define DUMP_INSTR_IN_UNIT_TEST(I, FMT) { QQmlJS::V4InstrData<QQmlJS::V4Instr::I> i; memset(&i, 0, sizeof(i)); bc.append(i); }
@@ -1130,15 +1106,15 @@ void tst_v4::debuggingDumpInstructions()
     bc.dump(start, end);
 
     // ensure that the output was expected.
-    qInstallMessageHandler(old);
-    QCOMPARE(messages.count(), expected.count());
-    for (int ii = 0; ii < messages.count(); ++ii) {
+    const int messageCount = messageHandler.messages().count();
+    QCOMPARE(messageCount, expected.count());
+    for (int ii = 0; ii < messageCount; ++ii) {
         // Calculating the destination address of a null jump/branch instruction is tricky
         // so instead we simply don't compare that part of those instructions.
         QRegExp ignoreAddress("\\bAddress\\((\\w*)\\)");
         ignoreAddress.setMinimal(true);
         QString expectOut = expected.at(ii); expectOut.replace(ignoreAddress, "");
-        QString actualOut = messages.at(ii); actualOut.replace(ignoreAddress, "");
+        QString actualOut = messageHandler.messages().at(ii); actualOut.replace(ignoreAddress, "");
         QCOMPARE(actualOut, expectOut);
     }
 }
index 38c9bb3..bce1366 100644 (file)
@@ -661,13 +661,6 @@ void tst_qquickimage::sourceSize_QTBUG_16389()
     delete window;
 }
 
-static int numberOfWarnings = 0;
-static void checkWarnings(QtMsgType, const QMessageLogContext &, const QString &msg)
-{
-    if (!msg.contains("QGLContext::makeCurrent(): Failed."))
-        numberOfWarnings++;
-}
-
 // QTBUG-15690
 void tst_qquickimage::nullPixmapPaint()
 {
@@ -679,12 +672,11 @@ void tst_qquickimage::nullPixmapPaint()
     QTRY_VERIFY(image != 0);
     image->setSource(SERVER_ADDR + QString("/no-such-file.png"));
 
-    QtMessageHandler previousMsgHandler = qInstallMessageHandler(checkWarnings);
-
+    QQmlTestMessageHandler messageHandler;
     // used to print "QTransform::translate with NaN called"
     QPixmap pm = QPixmap::fromImage(window->grabWindow());
-    qInstallMessageHandler(previousMsgHandler);
-    QVERIFY(numberOfWarnings == 0);
+    const QStringList glErrors =  messageHandler.messages().filter(QLatin1String("QGLContext::makeCurrent(): Failed."), Qt::CaseInsensitive);
+    QVERIFY2(glErrors.size() == messageHandler.messages().size(), qPrintable(messageHandler.messageString()));
     delete image;
 
     delete window;
index af628df..51ce74e 100644 (file)
@@ -259,18 +259,10 @@ private:
     }
 #endif
 
-    static void errorMsgHandler(QtMsgType, const QMessageLogContext &, const QString &)
-    {
-        ++m_errorCount;
-    }
-
     QQuickView *m_view;
     QString testForView;
-    static int m_errorCount;
 };
 
-int tst_QQuickListView::m_errorCount = 0;
-
 class TestObject : public QObject
 {
     Q_OBJECT
@@ -6785,8 +6777,7 @@ void tst_QQuickListView::parentBinding()
 {
     QQuickView *window = createView();
 
-    m_errorCount = 0;
-    QtMessageHandler old = qInstallMessageHandler(errorMsgHandler);
+    QQmlTestMessageHandler messageHandler;
 
     window->setSource(testFileUrl("parentBinding.qml"));
     window->show();
@@ -6805,9 +6796,7 @@ void tst_QQuickListView::parentBinding()
     QCOMPARE(item->height(), listview->height()/12);
 
     // there should be no transient binding error
-    QVERIFY(!m_errorCount);
-
-    qInstallMessageHandler(old);
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
 
     delete window;
 }
index b9a18ee..baba59a 100644 (file)
@@ -1722,111 +1722,109 @@ void tst_qquickpositioners::test_flow_implicit_resize()
     delete window;
 }
 
-QString warningMessage;
-
-void interceptWarnings(QtMsgType type, const QMessageLogContext &, const QString &msg)
-{
-    Q_UNUSED( type );
-    warningMessage = msg;
-}
-
 void tst_qquickpositioners::test_conflictinganchors()
 {
-    QtMessageHandler oldMsgHandler = qInstallMessageHandler(interceptWarnings);
+    QQmlTestMessageHandler messageHandler;
     QQmlEngine engine;
     QQmlComponent component(&engine);
 
     component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QVERIFY(warningMessage.isEmpty());
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     delete item;
 
     component.setData("import QtQuick 2.0\nRow { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QVERIFY(warningMessage.isEmpty());
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     delete item;
 
     component.setData("import QtQuick 2.0\nGrid { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QVERIFY(warningMessage.isEmpty());
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     delete item;
 
     component.setData("import QtQuick 2.0\nFlow { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QVERIFY(warningMessage.isEmpty());
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     delete item;
 
     component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; anchors.top: parent.top } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
-    warningMessage.clear();
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
+    messageHandler.clear();
     delete item;
 
     component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
-    warningMessage.clear();
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
+    messageHandler.clear();
     delete item;
 
     component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; anchors.left: parent.left } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QVERIFY(warningMessage.isEmpty());
-    warningMessage.clear();
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     delete item;
 
     component.setData("import QtQuick 2.0\nRow { Item { width: 100; height: 100; anchors.left: parent.left } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
-    warningMessage.clear();
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
+    messageHandler.clear();
     delete item;
 
     component.setData("import QtQuick 2.0\nRow { width: 100; height: 100; Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
-    warningMessage.clear();
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
+    messageHandler.clear();
     delete item;
 
     component.setData("import QtQuick 2.0\nRow { Item { width: 100; height: 100; anchors.top: parent.top } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QVERIFY(warningMessage.isEmpty());
-    warningMessage.clear();
+    QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
     delete item;
 
     component.setData("import QtQuick 2.0\nGrid { Item { width: 100; height: 100; anchors.horizontalCenter: parent.horizontalCenter } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
-    warningMessage.clear();
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
+    messageHandler.clear();
     delete item;
 
     component.setData("import QtQuick 2.0\nGrid { Item { width: 100; height: 100; anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
-    warningMessage.clear();
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
+    messageHandler.clear();
     delete item;
 
     component.setData("import QtQuick 2.0\nFlow { Item { width: 100; height: 100; anchors.verticalCenter: parent.verticalCenter } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
+    messageHandler.clear();
     delete item;
 
     component.setData("import QtQuick 2.0\nFlow {  width: 100; height: 100; Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
     item = qobject_cast<QQuickItem*>(component.create());
     QVERIFY(item);
-    QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
-    qInstallMessageHandler(oldMsgHandler);
+    QCOMPARE(messageHandler.messages().size(), 1);
+    QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
     delete item;
 }
 
index 94452b1..aa20967 100644 (file)
@@ -195,9 +195,8 @@ void tst_QQuickView::errors()
 {
     QQuickView *view = new QQuickView;
     QVERIFY(view);
-    QtMessageHandler old = qInstallMessageHandler(silentErrorsMsgHandler);
+    QQmlTestMessageHandler messageHandler;
     view->setSource(testFileUrl("error1.qml"));
-    qInstallMessageHandler(old);
     QVERIFY(view->status() == QQuickView::Error);
     QVERIFY(view->errors().count() == 1);
     delete view;
index 57c016a..eaefb1f 100644 (file)
@@ -46,6 +46,8 @@
 #include <QtQml/QQmlContext>
 #include <QtQml/QQmlEngine>
 #include <QtCore/QTextStream>
+#include <QtCore/QDebug>
+#include <QtCore/QMutexLocker>
 
 QQmlDataTest *QQmlDataTest::m_instance = 0;
 
@@ -107,3 +109,30 @@ QByteArray QQmlDataTest::msgComponentError(const QQmlComponent &c,
     }
     return result.toLocal8Bit();
 }
+
+Q_GLOBAL_STATIC(QMutex, qQmlTestMessageHandlerMutex)
+
+QQmlTestMessageHandler *QQmlTestMessageHandler::m_instance = 0;
+
+void QQmlTestMessageHandler::messageHandler(QtMsgType, const QMessageLogContext &, const QString &message)
+{
+    QMutexLocker locker(qQmlTestMessageHandlerMutex());
+    if (QQmlTestMessageHandler::m_instance)
+        QQmlTestMessageHandler::m_instance->m_messages.push_back(message);
+}
+
+QQmlTestMessageHandler::QQmlTestMessageHandler()
+{
+    QMutexLocker locker(qQmlTestMessageHandlerMutex());
+    Q_ASSERT(!QQmlTestMessageHandler::m_instance);
+    QQmlTestMessageHandler::m_instance = this;
+    m_oldHandler = qInstallMessageHandler(messageHandler);
+}
+
+QQmlTestMessageHandler::~QQmlTestMessageHandler()
+{
+    QMutexLocker locker(qQmlTestMessageHandlerMutex());
+    Q_ASSERT(QQmlTestMessageHandler::m_instance);
+    qInstallMessageHandler(m_oldHandler);
+    QQmlTestMessageHandler::m_instance = 0;
+}
index 4a5c917..eff54b3 100644 (file)
@@ -45,6 +45,7 @@
 #include <QtCore/QDir>
 #include <QtCore/QUrl>
 #include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
 #include <QtTest/QTest>
 
 QT_FORWARD_DECLARE_CLASS(QQmlComponent)
@@ -87,4 +88,24 @@ private:
     QString m_directory;
 };
 
+class QQmlTestMessageHandler
+{
+    Q_DISABLE_COPY(QQmlTestMessageHandler)
+public:
+    QQmlTestMessageHandler();
+    ~QQmlTestMessageHandler();
+
+    const QStringList &messages() const { return m_messages; }
+    const QString messageString() const { return m_messages.join(QLatin1Char('\n')); }
+
+    void clear() { m_messages.clear(); }
+
+private:
+    static void messageHandler(QtMsgType, const QMessageLogContext &, const QString &message);
+
+    static QQmlTestMessageHandler *m_instance;
+    QStringList m_messages;
+    QtMessageHandler m_oldHandler;
+};
+
 #endif // QQMLTESTUTILS_H