diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-06-29 01:02:07 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-06-29 01:02:07 +0200 |
commit | dd333172e2ade1db6d0af72b4ed44262c2b4d8c7 (patch) | |
tree | 16301a9b938826cf4b78b751907378d96423c5d0 /tests/auto/quick/qquickpathview/tst_qquickpathview.cpp | |
parent | 3d266d90cb920375bb856844baea290e52355aad (diff) | |
parent | ffeaac704efc9eb85464d0a401d98e28991ec4d3 (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: I800f39ea59efd6049d3226ec27b8ecb3f6e9ae28
Diffstat (limited to 'tests/auto/quick/qquickpathview/tst_qquickpathview.cpp')
-rw-r--r-- | tests/auto/quick/qquickpathview/tst_qquickpathview.cpp | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index 7a6f302403..7d297d3fa2 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -144,6 +144,7 @@ private slots: void movementDirection_data(); void movementDirection(); void removePath(); + void objectModelMove(); }; class TestObject : public QObject @@ -2530,6 +2531,53 @@ void tst_QQuickPathView::removePath() QVERIFY(QMetaObject::invokeMethod(pathview, "setPath")); } +/* + Tests that moving items in an ObjectModel and then deleting the view + doesn't cause heap-use-after-free when run through ASAN. + + The test case is based on a Qt Quick Controls 2 test where the issue was + discovered. +*/ +void tst_QQuickPathView::objectModelMove() +{ + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("objectModelMove.qml")); + window->show(); + + // Create the view. + QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "newView")); + QPointer<QQuickPathView> pathView = window->rootObject()->property("pathViewItem").value<QQuickPathView*>(); + QVERIFY(pathView); + QCOMPARE(pathView->count(), 3); + pathView->highlightItem()->setObjectName("highlight"); + + // Move an item from index 0 to 1. + QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "move")); + QCOMPARE(pathView->count(), 3); + + // Keep track of the amount of listeners + QVector<QString> itemObjectNames; + itemObjectNames << QLatin1String("red") << QLatin1String("green") << QLatin1String("blue"); + QVector<QQuickItem*> childItems; + for (const QString itemObjectName : qAsConst(itemObjectNames)) { + QQuickItem *childItem = findItem<QQuickItem>(pathView, itemObjectName); + QVERIFY(childItem); + childItems.append(childItem); + } + + // Destroy the view (via destroy()). + QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "destroyView")); + // Ensure that the view has been destroyed. This check is also necessary in order for + // ASAN to complain (it will complain after the test function has finished). + QTRY_VERIFY(pathView.isNull()); + // By this point, all of its cached items should have been released, + // which means none of the items should have any listeners. + for (const auto childItem : qAsConst(childItems)) { + const QQuickItemPrivate *childItemPrivate = QQuickItemPrivate::get(childItem); + QCOMPARE(childItemPrivate->changeListeners.size(), 0); + } +} + QTEST_MAIN(tst_QQuickPathView) #include "tst_qquickpathview.moc" |