El dimecres, 10 d’octubre de 2018, a les 16:33:43 CEST, Jaime va escriure:
> Hello,
> 
>   About
> https://build.kde.org/job/Frameworks/job/kio/job/kf5-qt5%20SUSEQt5.10/429/testReport/junit/(root)/TestSuite/kiowidgets_kdirmodeltest/
> 
>   I'm only able to reproduce the crash 1/7 times I run ctest -j3, never if
> I run the test alone or run make test.

FWIW I can reproduce the ASAN error quite easily with

while [ true ]; do ASAN_OPTIONS=detect_leaks=0 ./bin/kdirmodeltest 
testOverwriteFileWithDir; if [ $? -ne 0 ]; then break; fi; done

it doesn't go more than two or three loops.

> 
>   I've tried applying what worked for me in the 4th revision of
> https://phabricator.kde.org/D10742 to kdirmodel.cpp around line 600, but
> without success.
> 
>   Any idea how to fix it is welcomed.

From what i see, the problem is that you're storing QModelIndexes and using 
them later when the model has changed. 

This is not correct, you can only use a QModelIndex when you just got it or 
when it's passed it to you, if you need to store it you need to use 
QPersistentModelIndex.

I don't understand much the test, but i think the attached patch is a good fix, 
i.e. use the model indexes as soon as they happen and not store them. Also 
makes the test pass "forever" here.

Cheers,
  Albert

> 
> Best Regards.
> Jaime.
> 

diff --git a/autotests/kdirmodeltest.cpp b/autotests/kdirmodeltest.cpp
index 3c0ab0bb..c997ab55 100644
--- a/autotests/kdirmodeltest.cpp
+++ b/autotests/kdirmodeltest.cpp
@@ -1269,10 +1269,23 @@ void KDirModelTest::testOverwriteFileWithDir() // #151851 c4
     const QString file = path + "toplevelfile_1";
     const int oldTopLevelRowCount = m_dirModel->rowCount();
 
-    QSignalSpy spyRowsRemoved(m_dirModel, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+    bool removalWithinTopLevel = false;
+    bool dataChangedAtFirstLevel = false;
+    connect(m_dirModel, &KDirModel::rowsRemoved, this, [&removalWithinTopLevel](const QModelIndex &index) {
+        if (!index.isValid()) {
+            // yes, that's what we have been waiting for
+            removalWithinTopLevel = true;
+        }
+    });
+    connect(m_dirModel, &KDirModel::dataChanged, this, [&dataChangedAtFirstLevel](const QModelIndex &index) {
+        if (index.isValid() && !index.parent().isValid()) {
+            // a change of a node whose parent is root, yay, that's it
+            dataChangedAtFirstLevel = true;
+        }
+    });
+
     checkedConnect(m_dirModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
                    &m_eventLoop, SLOT(exitLoop()));
-    QSignalSpy spyDataChanged(m_dirModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
 
     KIO::Job *job = KIO::move(QUrl::fromLocalFile(dir), QUrl::fromLocalFile(file), KIO::HideProgressInfo);
     job->setUiDelegate(nullptr);
@@ -1285,24 +1298,9 @@ void KDirModelTest::testOverwriteFileWithDir() // #151851 c4
 
     // Wait for a removal within the top level (that's for the old file going away), and also
     // for a dataChanged which notifies us that a file has become a directory
-    bool removalWithinTopLevel = false;
-    bool dataChangedAtFirstLevel = false;
+
     int retries = 0;
     while ((!removalWithinTopLevel || !dataChangedAtFirstLevel) && retries < 100) {
-        for (int i = 0; i < spyRowsRemoved.size() && !removalWithinTopLevel; ++i) {
-            QModelIndex parent = spyRowsRemoved[i][0].value<QModelIndex>();
-            if (!parent.isValid()) {
-                // yes, that's what we have been waiting for
-                removalWithinTopLevel = true;
-            }
-        }
-        for (int i = 0; i < spyDataChanged.size() && !dataChangedAtFirstLevel; ++i) {
-            QModelIndex idx = spyDataChanged[i][0].value<QModelIndex>();
-            if (idx.isValid() && !idx.parent().isValid()) {
-                // a change of a node whose parent is root, yay, that's it
-                dataChangedAtFirstLevel = true;
-            }
-        }
         QTest::qWait(10);
         ++retries;
     }

Reply via email to