on bionic help sign in
unity8/tests/plugins/Utils/QLimitProxyModelTest.cpp
611 lines 19 kB history raw
1/*
2 * Copyright (C) 2011, 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17// local
18#include "qlimitproxymodelqml.h"
19#include "ModelTest.h"
21// Qt
22#include <QTest>
23#include <QSignalSpy>
24#include <QModelIndex>
25#include <QAbstractListModel>
26#include <QDebug>
29class MockListModel : public QAbstractListModel
31 Q_OBJECT
33public:
34 MockListModel(QObject* parent = 0)
35 : QAbstractListModel(parent)
36 {
37 }
39 int rowCount(const QModelIndex& /* parent */ = QModelIndex()) const override
40 {
41 return m_list.size();
42 }
44 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
45 {
46 if (!index.isValid() || index.row() < 0 || index.row() >= m_list.size() || role != Qt::DisplayRole) {
47 return QVariant();
48 }
49 return QVariant(m_list[index.row()]);
50 }
52 QHash<int, QByteArray> roleNames() const override
53 {
54 return m_roles;
55 }
57 void setRoles(const QHash<int,QByteArray> &roles) {
58 m_roles = roles;
59 }
61 void clear()
62 {
63 beginRemoveRows(QModelIndex(), 0, m_list.count() - 1);
64 m_list.clear();
65 endRemoveRows();
66 }
68 bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override {
69 beginInsertRows(parent, row, row+count-1);
70 for (int i=0; i<count; i++) {
71 m_list.insert(i+row, QString::number(i));
72 }
73 endInsertRows();
74 return true;
75 }
77 bool appendRows(QStringList &rows, const QModelIndex &parent=QModelIndex()) {
78 beginInsertRows(parent, rowCount(), rowCount() + rows.count() - 1);
79 m_list.append(rows);
80 endInsertRows();
81 return true;
82 }
84 bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override {
85 beginRemoveRows(parent, row, row+count-1);
86 for (int i=0; i<count; i++) {
87 m_list.removeAt(row);
88 }
89 endRemoveRows();
90 return true;
91 }
93private:
94 QStringList m_list;
95 QHash<int, QByteArray> m_roles;
96};
98class MirrorModel : public QObject
100 Q_OBJECT
102public:
103 MirrorModel(QAbstractItemModel *model) : m_mirror(model)
104 {
105 connect(model, &QAbstractItemModel::rowsInserted, this, &MirrorModel::rowsInserted);
106 connect(model, &QAbstractItemModel::rowsRemoved, this, &MirrorModel::rowsRemoved);
107 connect(model, &QAbstractItemModel::dataChanged, this, &MirrorModel::dataChanged);
108 }
110 void check()
111 {
112 QCOMPARE(m_list.count(), m_mirror->rowCount());
113 for (int i = 0; i < m_list.count(); ++i) {
114 QCOMPARE(m_list[i], m_mirror->data(m_mirror->index(i, 0)).toString());
115 }
116 }
118private Q_SLOTS:
119 void rowsInserted(const QModelIndex &parent, int start, int end)
120 {
121 QVERIFY(!parent.isValid());
122 for (int i = start; i <= end; ++i) {
123 m_list.insert(i, m_mirror->data(m_mirror->index(i, 0)).toString());
124 }
125 }
127 void rowsRemoved(const QModelIndex &parent, int start, int end)
128 {
129 QVERIFY(!parent.isValid());
130 for (int i = end; i >= start; --i) {
131 m_list.removeAt(i);
132 }
133 }
135 void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
136 {
137 QVERIFY(topLeft.isValid());
138 QVERIFY(bottomRight.isValid());
139 QVERIFY(!topLeft.parent().isValid());
140 QVERIFY(!bottomRight.parent().isValid());
141 for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
142 m_list[i] = m_mirror->data(m_mirror->index(i, 0)).toString();
143 }
144 }
147private:
148 QStringList m_list;
149 QAbstractItemModel *m_mirror;
150};
152class QLimitProxyModelTest : public QObject
154 Q_OBJECT
156private Q_SLOTS:
158 void initTestCase() {
159 qRegisterMetaType<QModelIndex>("QModelIndex");
160 }
162 void testRoleNamesSetAfter()
163 {
164 QLimitProxyModelQML proxy;
165 MockListModel model;
166 QHash<int, QByteArray> roles;
168 proxy.setModel(&model);
170 roles[0] = "role0";
171 roles[1] = "role1";
172 model.setRoles(roles);
173 QCOMPARE(model.roleNames(), proxy.roleNames());
174 }
176 void testRoleNamesSetBefore()
177 {
178 QLimitProxyModelQML proxy;
179 MockListModel model;
180 QHash<int, QByteArray> roles;
182 roles[0] = "role0";
183 roles[1] = "role1";
184 model.setRoles(roles);
186 proxy.setModel(&model);
187 QCOMPARE(model.roleNames(), proxy.roleNames());
188 }
190 void testCountSetAfter()
191 {
192 QLimitProxyModelQML proxy;
193 MockListModel model;
194 model.insertRows(0, 5);
196 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
198 proxy.setModel(&model);
199 QCOMPARE(proxy.rowCount(), 5);
200 QVERIFY(spyOnCountChanged.count() >= 1);
201 }
203 void testCountInsert()
204 {
205 QLimitProxyModelQML proxy;
206 MockListModel model;
208 proxy.setModel(&model);
210 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
212 model.insertRows(0, 5);
213 QCOMPARE(proxy.rowCount(), 5);
214 QCOMPARE(spyOnCountChanged.count(), 1);
215 }
217 void testCountRemove()
218 {
219 QLimitProxyModelQML proxy;
220 MockListModel model;
221 model.insertRows(0, 5);
223 proxy.setModel(&model);
225 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
227 model.removeRows(0, 3);
228 QCOMPARE(proxy.rowCount(), 2);
229 QCOMPARE(spyOnCountChanged.count(), 1);
230 }
232 void testLimitCount()
233 {
234 QLimitProxyModelQML proxy;
235 MockListModel model;
237 proxy.setModel(&model);
238 proxy.setLimit(3);
240 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
242 model.insertRows(0, 5);
243 QCOMPARE(proxy.rowCount(), 3);
244 QCOMPARE(spyOnCountChanged.count(), 1);
245 }
247 void testLimitLesserThanCount()
248 {
249 QLimitProxyModelQML proxy;
250 MockListModel model;
251 QList<QVariant> arguments;
252 model.insertRows(0, 10);
254 proxy.setModel(&model);
256 QSignalSpy spyOnRowsRemoved(&proxy, &QLimitProxyModelQML::rowsRemoved);
257 QSignalSpy spyOnRowsInserted(&proxy, &QLimitProxyModelQML::rowsInserted);
258 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
260 proxy.setLimit(5);
261 QCOMPARE(spyOnRowsInserted.count(), 0);
262 QCOMPARE(spyOnCountChanged.count(), 1);
263 QCOMPARE(spyOnRowsRemoved.count(), 1);
264 arguments = spyOnRowsRemoved.takeFirst();
265 QCOMPARE(arguments.at(1).toInt(), 5);
266 QCOMPARE(arguments.at(2).toInt(), 9);
267 QCOMPARE(proxy.rowCount(), 5);
268 spyOnRowsRemoved.clear();
269 spyOnCountChanged.clear();
271 proxy.setLimit(7);
272 QCOMPARE(spyOnRowsInserted.count(), 1);
273 QCOMPARE(spyOnRowsRemoved.count(), 0);
274 QCOMPARE(spyOnCountChanged.count(), 1);
275 arguments = spyOnRowsInserted.takeFirst();
276 QCOMPARE(arguments.at(1).toInt(), 5);
277 QCOMPARE(arguments.at(2).toInt(), 6);
278 QCOMPARE(proxy.rowCount(), 7);
279 spyOnRowsInserted.clear();
280 spyOnCountChanged.clear();
282 proxy.setLimit(3);
283 QCOMPARE(spyOnRowsRemoved.count(), 1);
284 QCOMPARE(spyOnRowsInserted.count(), 0);
285 QCOMPARE(spyOnCountChanged.count(), 1);
286 arguments = spyOnRowsRemoved.takeFirst();
287 QCOMPARE(arguments.at(1).toInt(), 3);
288 QCOMPARE(arguments.at(2).toInt(), 6);
289 QCOMPARE(proxy.rowCount(), 3);
290 spyOnRowsRemoved.clear();
291 spyOnCountChanged.clear();
292 }
294 void testLimitGreaterThanCount()
295 {
296 QLimitProxyModelQML proxy;
297 MockListModel model;
298 QList<QVariant> arguments;
299 model.insertRows(0, 5);
301 proxy.setModel(&model);
303 QSignalSpy spyOnRowsRemoved(&proxy, &QLimitProxyModelQML::rowsRemoved);
304 QSignalSpy spyOnRowsInserted(&proxy, &QLimitProxyModelQML::rowsInserted);
305 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
307 proxy.setLimit(7);
308 QCOMPARE(spyOnRowsRemoved.count(), 0);
309 QCOMPARE(spyOnRowsInserted.count(), 0);
310 QCOMPARE(spyOnCountChanged.count(), 0);
311 QCOMPARE(proxy.rowCount(), 5);
313 proxy.setLimit(5);
314 QCOMPARE(spyOnRowsRemoved.count(), 0);
315 QCOMPARE(spyOnRowsInserted.count(), 0);
316 QCOMPARE(spyOnCountChanged.count(), 0);
317 QCOMPARE(proxy.rowCount(), 5);
319 proxy.setLimit(3);
320 QCOMPARE(spyOnRowsInserted.count(), 0);
321 QCOMPARE(spyOnRowsRemoved.count(), 1);
322 QCOMPARE(spyOnCountChanged.count(), 1);
323 arguments = spyOnRowsRemoved.takeFirst();
324 QCOMPARE(arguments.at(1).toInt(), 3);
325 QCOMPARE(arguments.at(2).toInt(), 4);
326 QCOMPARE(proxy.rowCount(), 3);
327 spyOnRowsRemoved.clear();
328 spyOnCountChanged.clear();
330 proxy.setLimit(4);
331 QCOMPARE(spyOnRowsRemoved.count(), 0);
332 QCOMPARE(spyOnRowsInserted.count(), 1);
333 QCOMPARE(spyOnCountChanged.count(), 1);
334 arguments = spyOnRowsInserted.takeFirst();
335 QCOMPARE(arguments.at(1).toInt(), 3);
336 QCOMPARE(arguments.at(2).toInt(), 3);
337 QCOMPARE(proxy.rowCount(), 4);
338 spyOnRowsInserted.clear();
339 spyOnCountChanged.clear();
341 proxy.setLimit(7);
342 QCOMPARE(spyOnRowsRemoved.count(), 0);
343 QCOMPARE(spyOnRowsInserted.count(), 1);
344 QCOMPARE(spyOnCountChanged.count(), 1);
345 arguments = spyOnRowsInserted.takeFirst();
346 QCOMPARE(arguments.at(1).toInt(), 4);
347 QCOMPARE(arguments.at(2).toInt(), 4);
348 QCOMPARE(proxy.rowCount(), 5);
349 spyOnRowsInserted.clear();
350 spyOnCountChanged.clear();
351 }
353 void testLimitMinusOne()
354 {
355 QLimitProxyModelQML proxy;
356 MockListModel model;
357 QList<QVariant> arguments;
358 model.insertRows(0, 5);
360 proxy.setModel(&model);
362 QSignalSpy spyOnRowsRemoved(&proxy, &QLimitProxyModelQML::rowsRemoved);
363 QSignalSpy spyOnRowsInserted(&proxy, &QLimitProxyModelQML::rowsInserted);
364 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
366 proxy.setLimit(7);
367 QCOMPARE(spyOnRowsRemoved.count(), 0);
368 QCOMPARE(spyOnRowsInserted.count(), 0);
369 QCOMPARE(spyOnCountChanged.count(), 0);
370 QCOMPARE(proxy.rowCount(), 5);
372 proxy.setLimit(-1);
373 QCOMPARE(spyOnRowsRemoved.count(), 0);
374 QCOMPARE(spyOnRowsInserted.count(), 0);
375 QCOMPARE(spyOnCountChanged.count(), 0);
376 QCOMPARE(proxy.rowCount(), 5);
378 proxy.setLimit(3);
379 QCOMPARE(spyOnRowsInserted.count(), 0);
380 QCOMPARE(spyOnRowsRemoved.count(), 1);
381 QCOMPARE(spyOnCountChanged.count(), 1);
382 arguments = spyOnRowsRemoved.takeFirst();
383 QCOMPARE(arguments.at(1).toInt(), 3);
384 QCOMPARE(arguments.at(2).toInt(), 4);
385 QCOMPARE(proxy.rowCount(), 3);
386 spyOnRowsRemoved.clear();
387 spyOnCountChanged.clear();
389 proxy.setLimit(-1);
390 QCOMPARE(spyOnRowsRemoved.count(), 0);
391 QCOMPARE(spyOnRowsInserted.count(), 1);
392 QCOMPARE(spyOnCountChanged.count(), 1);
393 arguments = spyOnRowsInserted.takeFirst();
394 QCOMPARE(arguments.at(1).toInt(), 3);
395 QCOMPARE(arguments.at(2).toInt(), 4);
396 QCOMPARE(proxy.rowCount(), 5);
397 spyOnRowsInserted.clear();
398 spyOnCountChanged.clear();
399 }
401 void testLimitInsert() {
402 QLimitProxyModelQML proxy;
403 MockListModel model;
404 QList<QVariant> arguments;
406 proxy.setModel(&model);
407 proxy.setLimit(7);
409 QSignalSpy spyOnRowsRemoved(&proxy, &QLimitProxyModelQML::rowsRemoved);
410 QSignalSpy spyOnRowsInserted(&proxy, &QLimitProxyModelQML::rowsInserted);
411 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
413 model.insertRows(0, 5);
414 QCOMPARE(spyOnRowsRemoved.count(), 0);
415 QCOMPARE(spyOnRowsInserted.count(), 1);
416 QCOMPARE(spyOnCountChanged.count(), 1);
417 arguments = spyOnRowsInserted.takeFirst();
418 QCOMPARE(arguments.at(1).toInt(), 0);
419 QCOMPARE(arguments.at(2).toInt(), 4);
420 QCOMPARE(proxy.rowCount(), 5);
421 spyOnRowsInserted.clear();
422 spyOnCountChanged.clear();
424 model.insertRows(2, 2);
425 QCOMPARE(spyOnRowsRemoved.count(), 0);
426 QCOMPARE(spyOnRowsInserted.count(), 1);
427 QCOMPARE(spyOnCountChanged.count(), 1);
428 arguments = spyOnRowsInserted.takeFirst();
429 QCOMPARE(arguments.at(1).toInt(), 2);
430 QCOMPARE(arguments.at(2).toInt(), 3);
431 QCOMPARE(proxy.rowCount(), 7);
432 spyOnRowsInserted.clear();
433 spyOnCountChanged.clear();
435 model.insertRows(7, 3);
436 QCOMPARE(proxy.rowCount(), 7);
437 QCOMPARE(spyOnRowsRemoved.count(), 0);
438 QCOMPARE(spyOnRowsInserted.count(), 0);
439 QCOMPARE(spyOnCountChanged.count(), 0);
440 }
442 void testLimitRemove() {
443 QLimitProxyModelQML proxy;
444 MockListModel model;
445 QList<QVariant> arguments;
447 proxy.setModel(&model);
448 proxy.setLimit(7);
450 model.insertRows(0, 12);
452 QCOMPARE(proxy.rowCount(), 7);
454 QSignalSpy spyOnRowsRemoved(&proxy, &QLimitProxyModelQML::rowsRemoved);
455 QSignalSpy spyOnRowsInserted(&proxy, &QLimitProxyModelQML::rowsInserted);
456 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
458 model.removeRows(7, 3);
459 QCOMPARE(proxy.rowCount(), 7);
460 QCOMPARE(spyOnRowsRemoved.count(), 0);
461 QCOMPARE(spyOnRowsInserted.count(), 0);
462 QCOMPARE(spyOnCountChanged.count(), 0);
464 model.removeRows(2, 2);
465 QCOMPARE(spyOnRowsRemoved.count(), 0);
466 QCOMPARE(spyOnRowsInserted.count(), 0);
467 QCOMPARE(spyOnCountChanged.count(), 0);
468 QCOMPARE(proxy.rowCount(), 7);
470 model.removeRows(0, 7);
471 QCOMPARE(spyOnRowsRemoved.count(), 1);
472 QCOMPARE(spyOnRowsInserted.count(), 0);
473 QCOMPARE(spyOnCountChanged.count(), 1);
474 arguments = spyOnRowsRemoved.takeFirst();
475 QCOMPARE(arguments.at(1).toInt(), 0);
476 QCOMPARE(arguments.at(2).toInt(), 6);
477 QCOMPARE(proxy.rowCount(), 0);
478 }
480 void testNestedProxyRoleNames() {
481 QLimitProxyModelQML proxy1, proxy2;
482 MockListModel model;
483 QHash<int, QByteArray> roles;
484 roles[0] = "role0";
485 roles[1] = "role1";
486 model.setRoles(roles);
488 proxy1.setModel(&model);
489 proxy2.setModel(&proxy1);
491 QCOMPARE(proxy2.roleNames(), model.roleNames());
492 }
494 void testModelTest() {
495 QLimitProxyModelQML proxy;
496 MockListModel model;
498 proxy.setModel(&model);
499 proxy.setLimit(7);
501 model.insertRows(0, 12);
503 ModelTest t1(&proxy);
504 }
506 void testModelChanged() {
507 QLimitProxyModelQML proxy;
508 MockListModel model, model2;
510 QSignalSpy spyOnModelChanged(&proxy, &QLimitProxyModelQML::modelChanged);
512 proxy.setModel(&model);
513 QCOMPARE(spyOnModelChanged.count(), 1);
515 proxy.setModel(&model2);
516 QCOMPARE(spyOnModelChanged.count(), 2);
518 proxy.setModel(&model);
519 QCOMPARE(spyOnModelChanged.count(), 3);
521 proxy.setModel(&model);
522 QCOMPARE(spyOnModelChanged.count(), 3);
523 }
525 void setSameModelTwice() {
526 QLimitProxyModelQML proxy;
527 MockListModel model;
529 proxy.setModel(&model);
530 proxy.setModel(&model);
532 QSignalSpy spyOnCountChanged(&proxy, &QLimitProxyModelQML::countChanged);
534 model.insertRows(0, 5);
535 QCOMPARE(proxy.rowCount(), 5);
536 QCOMPARE(spyOnCountChanged.count(), 1);
537 }
539 void testMirrorModel() {
540 QLimitProxyModelQML proxy;
541 MockListModel model;
542 MirrorModel mirror(&proxy);
544 proxy.setModel(&model);
545 proxy.setLimit(5);
547 // Checks what happens when the model already has
548 // more items than the limit and we add stuff to
549 // the front
550 model.insertRows(0, 7);
551 mirror.check();
552 model.insertRows(1, 3);
553 mirror.check();
554 model.clear();
555 mirror.check();
557 // Checks what happens when the model does
558 // not has more items than limit but adding
559 // stuff to its front makes it go past the limit
560 model.insertRows(0, 3);
561 mirror.check();
562 model.insertRows(1, 3);
563 mirror.check();
564 model.clear();
565 mirror.check();
567 // Checks what happens when the model does
568 // not has more items than limit and adding
569 // stuff to its front makes it not go past the limit
570 model.insertRows(0, 1);
571 mirror.check();
572 model.insertRows(1, 3);
573 mirror.check();
574 model.clear();
575 mirror.check();
577 // Checks what happens when the model already has
578 // more items than the limit and we remove stuff from
579 // the front but it still has more than the limit
580 model.insertRows(0, 10);
581 mirror.check();
582 model.removeRows(1, 3);
583 mirror.check();
584 model.clear();
585 mirror.check();
587 // Checks what happens when the model already has
588 // more items than the limit and we remove stuff from
589 // the front but it has less than the limit
590 model.insertRows(0, 6);
591 mirror.check();
592 model.removeRows(1, 3);
593 mirror.check();
594 model.clear();
595 mirror.check();
597 // Checks what happens when the model has
598 // less items than the limit and we remove stuff from
599 // the front
600 model.insertRows(0, 4);
601 mirror.check();
602 model.removeRows(1, 3);
603 mirror.check();
604 model.clear();
605 mirror.check();
606 }
607};
609QTEST_GUILESS_MAIN(QLimitProxyModelTest)
611#include "QLimitProxyModelTest.moc"