aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>2015-11-23 18:35:02 -0800
committerGabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>2015-12-07 16:10:24 +0000
commitd2305265af0552f9fcab4c93bed6b93e25a28f78 (patch)
tree8a0ac1dee758fea8bd2ba2ff5f3fb4008c426252 /tests/auto/quick
parentf9f99c43fbea600f61d065b30a5453e95dfa6ade (diff)
Auto-tests for fast model updates while flicking
Stress testing might sound unfair, but it can happen that the user is flicking the view while the model gets updated resulting in an internally inconsistent state. We need to cover this and start working on a solution. The test is initially blacklisted as it's not expected to pass all the time. Task-number: QTBUG 48870 Change-Id: I7c1e4fd1876f52dd2dad5a28584b571753ebe69a Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com> Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
Diffstat (limited to 'tests/auto/quick')
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST2
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug48870.qml24
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp132
3 files changed, 158 insertions, 0 deletions
diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST
index 269696ce8c..02adeacf05 100644
--- a/tests/auto/quick/qquicklistview/BLACKLIST
+++ b/tests/auto/quick/qquicklistview/BLACKLIST
@@ -2,3 +2,5 @@
*
[enforceRange_withoutHighlight]
osx
+[QTBUG_48870_fastModelUpdates]
+*
diff --git a/tests/auto/quick/qquicklistview/data/qtbug48870.qml b/tests/auto/quick/qquicklistview/data/qtbug48870.qml
new file mode 100644
index 0000000000..217f58af48
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug48870.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.6
+
+Rectangle {
+ width: 500
+ height: 500
+ color: "blue"
+
+ ListView {
+ objectName: "list"
+ anchors.fill: parent
+ model: testModel
+
+ delegate: Rectangle {
+ height: 50
+ width: ListView.view ? ListView.view.width : height
+ color: "green"
+
+ Text {
+ anchors.centerIn: parent
+ text: "Item " + index
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index a5de266636..ce2337ccb2 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -40,6 +40,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
+#include <QtQuick/private/qquickitemview_p_p.h>
#include <QtQuick/private/qquicklistview_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmlobjectmodel_p.h>
@@ -249,6 +250,7 @@ private slots:
void contentHeightWithDelayRemove_data();
void QTBUG_48044_currentItemNotVisibleAfterTransition();
+ void QTBUG_48870_fastModelUpdates();
private:
template <class T> void items(const QUrl &source);
@@ -8295,6 +8297,136 @@ void tst_QQuickListView::QTBUG_48044_currentItemNotVisibleAfterTransition()
QVERIFY(!currentPriv->culled);
}
+static bool testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx)
+{
+ QHash<QQuickItem*, int> uniqueItems;
+
+ int skip = 0;
+ for (int i = 0; i < priv->visibleItems.count(); ++i) {
+ FxViewItem *item = priv->visibleItems.at(i);
+ if (!item) {
+ *failItem = Q_NULLPTR;
+ return false;
+ }
+#if 0
+ qDebug() << "\t" << item->index
+ << item->item
+ << item->position()
+ << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible");
+#endif
+ if (item->index == -1) {
+ ++skip;
+ } else if (item->index != priv->visibleIndex + i - skip) {
+ *nonUnique = false;
+ *failItem = item;
+ *expectedIdx = priv->visibleIndex + i - skip;
+ return false;
+ } else if (uniqueItems.contains(item->item)) {
+ *nonUnique = true;
+ *failItem = item;
+ *expectedIdx = uniqueItems.find(item->item).value();
+ return false;
+ }
+
+ uniqueItems.insert(item->item, item->index);
+ }
+
+ return true;
+}
+
+class QTBUG_48870_Model : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+
+ QTBUG_48870_Model()
+ : QAbstractListModel()
+ , m_rowCount(20)
+ {
+ QTimer *t = new QTimer(this);
+ t->setInterval(500);
+ t->start();
+
+ qsrand(qHash(QDateTime::currentDateTime()));
+ connect(t, &QTimer::timeout, this, &QTBUG_48870_Model::updateModel);
+ }
+
+ int rowCount(const QModelIndex &) const
+ {
+ return m_rowCount;
+ }
+
+ QVariant data(const QModelIndex &, int) const
+ {
+ return QVariant();
+ }
+
+public Q_SLOTS:
+ void updateModel()
+ {
+ if (m_rowCount > 10) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginRemoveRows(QModelIndex(), rnum, rnum);
+ m_rowCount--;
+ endRemoveRows();
+ }
+ }
+ if (m_rowCount < 20) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginInsertRows(QModelIndex(), rnum, rnum);
+ m_rowCount++;
+ endInsertRows();
+ }
+ }
+ }
+
+private:
+ int m_rowCount;
+};
+
+void tst_QQuickListView::QTBUG_48870_fastModelUpdates()
+{
+ QTBUG_48870_Model model;
+
+ QQuickView *window = createView();
+ QVERIFY(window);
+ QQmlContext *ctxt = window->rootContext();
+ QVERIFY(ctxt);
+ ctxt->setContextProperty("testModel", &model);
+
+ window->setSource(testFileUrl("qtbug48870.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItemViewPrivate *priv = QQuickItemViewPrivate::get(listview);
+ bool nonUnique;
+ FxViewItem *item = Q_NULLPTR;
+ int expectedIdx;
+ QVERIFY(testVisibleItems(priv, &nonUnique, &item, &expectedIdx));
+
+ for (int i = 0; i < 10; i++) {
+ QTest::qWait(100);
+ QVERIFY2(testVisibleItems(priv, &nonUnique, &item, &expectedIdx),
+ qPrintable(!item ? QString("Unexpected null item")
+ : nonUnique ? QString("Non-unique item at %1 and %2").arg(item->index).arg(expectedIdx)
+ : QString("Found index %1, expected index is %3").arg(item->index).arg(expectedIdx)));
+ if (i % 3 != 0) {
+ if (i & 1)
+ flick(window, QPoint(100, 200), QPoint(100, 0), 100);
+ else
+ flick(window, QPoint(100, 200), QPoint(100, 400), 100);
+ }
+ }
+
+ delete window;
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"