Fix tst_qquickfolderlistmodel flakiness using QSignalSpy::wait.
authorDavid Faure <david.faure@kdab.com>
Fri, 16 Aug 2013 11:05:38 +0000 (13:05 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 16 Aug 2013 18:07:19 +0000 (20:07 +0200)
The signal is emitted in a thread, so creating the spy afterwards
is racy (due to isSignalConnected() at the beginning of QMetaObject::activate).
Creating the spy before hand fixes the race, and using QSignalSpy::wait()
leads to much smaller code, in addition.
Note that the call to wait() itself isn't racy, even if it happens "after" the
signal emission: the signal goes via the event loop so it will always be received
by the main thread within the call to wait(), never before.

In addition setPath() is called once upon creation, and again via the
setProperty call. If we don't wait for the initial listing to happen,
we're replacing it, and then folderChanged is never emitted.

Change-Id: Iab7eada2e9db8ba710f05bc3b82941c782f36467
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp

index e35a9f7..7045263 100644 (file)
 #include <qt_windows.h>
 #endif
 
-static bool waitForSignal(QObject* obj, const char* signal, int timeout = 10000)
-{
-    QEventLoop loop;
-    QObject::connect(obj, signal, &loop, SLOT(quit()));
-    QTimer timer;
-    QSignalSpy timeoutSpy(&timer, SIGNAL(timeout()));
-    if (timeout > 0) {
-        QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
-        timer.setSingleShot(true);
-        timer.start(timeout);
-    }
-    loop.exec();
-    return timeoutSpy.isEmpty();
-}
-
 // From qquickfolderlistmodel.h
 const int FileNameRole = Qt::UserRole+1;
 const int FilePathRole = Qt::UserRole+2;
@@ -131,8 +116,16 @@ void tst_qquickfolderlistmodel::basicProperties()
     QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
     QVERIFY(flm != 0);
 
+    QCOMPARE(flm->property("nameFilters").toStringList(), QStringList() << "*.qml"); // from basic.qml
+    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(QDir::currentPath()));
+
+    // wait for the initial directory listing (it will find at least the "data" dir,
+    // and other dirs on Windows).
+    QTRY_VERIFY(flm->property("count").toInt() > 0);
+
+    QSignalSpy folderChangedSpy(flm, SIGNAL(folderChanged()));
     flm->setProperty("folder", dataDirectoryUrl());
-    ::waitForSignal(flm, SIGNAL(folderChanged()), 0);
+    QVERIFY(folderChangedSpy.wait());
     QCOMPARE(flm->property("count").toInt(), 5);
     QCOMPARE(flm->property("folder").toUrl(), dataDirectoryUrl());
     QCOMPARE(flm->property("parentFolder").toUrl(), QUrl::fromLocalFile(QDir(directory()).canonicalPath()));