@@ -0,0 +1,206 @@
2+ * Copyright (C) 2013 Canonical, Ltd.
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.
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.
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/>.
17+ * Nick Dedekind <nick.dedekind@canonical.com>
20+#include "indicatorsmanager.h"
22+#include "unitymenumodelstack.h"
26+#include <unitymenumodel.h>
28+class UnityMenuModelStackTest : public QObject
35+ m_model = new UnityMenuModel();
36+ m_headChanged = false;
37+ m_tailChanged = false;
46+ void testHeadOnSetHead()
48+ UnityMenuModelStack stack;
49+ connect(&stack, SIGNAL(headChanged(UnityMenuModel*)), this, SLOT(onHeadChanged()));
50+ stack.setHead(m_model);
52+ QCOMPARE(stack.head(), m_model);
53+ QCOMPARE(m_headChanged, true);
56+ void testTailOnSetHead()
58+ UnityMenuModelStack stack;
59+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
60+ stack.setHead(m_model);
62+ QCOMPARE(stack.tail(), m_model);
63+ QCOMPARE(m_tailChanged, true);
66+ void testPushPop_data() {
67+ QTest::addColumn<int>("menuDepth");
68+ QTest::addColumn<int>("subMenuCount");
69+ QTest::addColumn<int>("subMenuIndex");
71+ QTest::newRow("depth=0") << 0 << 1 << 0;
72+ QTest::newRow("depth=1") << 1 << 1 << 0;
73+ QTest::newRow("depth=8") << 8 << 2 << 1;
78+ QFETCH(int, menuDepth);
79+ QFETCH(int, subMenuCount);
80+ QFETCH(int, subMenuIndex);
82+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
84+ UnityMenuModelStack stack;
85+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
87+ QList<UnityMenuModel*> models;
90+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
91+ stack.push(child, childIndex);
92+ QCOMPARE(stack.count(), count+1);
97+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
99+ QCOMPARE(stack.count(), models.count());
100+ QCOMPARE(stack.count(), menuDepth+1);
101+ while(stack.count() > 0) {
102+ m_tailChanged = false;
104+ QCOMPARE(stack.pop(), models.takeLast());
106+ QCOMPARE(m_tailChanged, true);
107+ if (stack.count()) {
108+ QCOMPARE(stack.tail(), models.last());
111+ QCOMPARE(m_tailChanged, true);
114+ void testPopOnRemove_data() {
115+ QTest::addColumn<int>("menuDepth");
116+ QTest::addColumn<int>("subMenuCount");
117+ QTest::addColumn<int>("subMenuIndex");
118+ QTest::addColumn<int>("removeIndex");
119+ QTest::addColumn<int>("resultCount");
121+ QTest::newRow("removeIndexBefore") << 4 << 2 << 1 << 0 << 5;
122+ QTest::newRow("removeCurrentIndex") << 4 << 2 << 0 << 0 << 1;
123+ QTest::newRow("removeIndexAfter") << 4 << 2 << 0 << 1 << 5;
126+ void testPopOnRemove()
128+ QFETCH(int, menuDepth);
129+ QFETCH(int, subMenuCount);
130+ QFETCH(int, subMenuIndex);
131+ QFETCH(int, removeIndex);
132+ QFETCH(int, resultCount);
134+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
136+ UnityMenuModelStack stack;
138+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
139+ stack.push(child, childIndex);
141+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
143+ QCOMPARE(stack.count(), menuDepth+1);
145+ m_model->removeRow(removeIndex);
147+ waitFor([&stack, resultCount]() { return stack.count() == resultCount; }, 1000);
148+ QCOMPARE(stack.count(), resultCount);
152+ bool waitFor(std::function<bool()> functor, int ms) {
154+ QElapsedTimer timer;
156+ while(!functor() && timer.elapsed() < ms) { QTest::qWait(10); }
160+ QVariant recuseAddMenu(int subMenuCount, int depth_remaining)
164+ for (int i = 0; i < subMenuCount; i ++) {
166+ QVariantMap rowData;
168+ if (depth_remaining > 0) {
169+ row["submenu"] = recuseAddMenu(subMenuCount, depth_remaining-1);
172+ row["rowData"] = rowData;
180+ void recuseSubmenus(UnityMenuModel* model, int childIndex, std::function<void(UnityMenuModel*, int)> func) {
181+ UnityMenuModel* parent = model;
182+ UnityMenuModel* child = model;
186+ func(child, childIndex);
190+ child = qobject_cast<UnityMenuModel*>(parent->submenu(childIndex));
196+ void onHeadChanged() { m_headChanged = true; }
197+ void onTailChanged() { m_tailChanged = true; }
200+ UnityMenuModel* m_model;
205+QTEST_GUILESS_MAIN(UnityMenuModelStackTest)
206+#include "unitymenumodelstacktest.moc"