@@ -0,0 +1,255 @@
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"
29+#include <unitymenumodel.h>
31+ #define BUS_NAME "com.canonical.unity8.unitymenumodelstacktest"
32+ #define OBJECT_PATH "/com/canonical/unity8/unitymenumodelstack"
34+static void on_bus_acquired (GDBusConnection *bus, const gchar *name, gpointer user_data);
35+static void on_name_aquired (GDBusConnection *bus, const gchar *name, gpointer user_data);
36+static void on_name_lost (GDBusConnection *bus, const gchar *name, gpointer user_data);
39+class UnityMenuModelStackTest : public QObject
52+ GBusNameOwnerFlags flags;
53+ flags = (GBusNameOwnerFlags) (G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE);
55+ g_bus_own_name (G_BUS_TYPE_SESSION, BUS_NAME, flags,
56+ on_bus_acquired, on_name_aquired, on_name_lost, this, NULL);
59+ void cleanupTestCase()
62+ g_object_unref(m_connection);
69+ QFETCH(QString, test);
70+ QFETCH(int, menuDepth);
71+ QFETCH(int, subMenuCount);
73+ waitFor([this]() { return this->m_connected || this->m_failed; }, 500);
74+ QVERIFY(m_connected);
76+ const QString& path = QString(OBJECT_PATH) + "/" + test;
78+ m_menuUid = exportMenuModel(&m_menu, m_connection, path, subMenuCount, menuDepth);
80+ m_model = new UnityMenuModel;
81+ m_model->setBusName(BUS_NAME);
82+ m_model->setMenuObjectPath(path.toUtf8());
90+ if (m_menuUid != 0) {
91+ g_dbus_connection_unexport_menu_model(m_connection, m_menuUid);
95+ g_object_unref(m_menu);
100+ void testPushPop_data() {
101+ QTest::addColumn<QString>("test");
102+ QTest::addColumn<int>("menuDepth");
103+ QTest::addColumn<int>("subMenuCount");
104+ QTest::addColumn<int>("subMenuIndex");
106+ QTest::newRow("depth=0") << "testPushPop1" << 0 << 1 << 0;
107+ QTest::newRow("depth=1") << "testPushPop2" << 1 << 1 << 0;
108+ QTest::newRow("depth=8") << "testPushPop3" << 8 << 2 << 1;
113+ QFETCH(int, menuDepth);
114+ QFETCH(int, subMenuCount);
115+ QFETCH(int, subMenuIndex);
117+ UnityMenuModelStack stack;
118+ QList<UnityMenuModel*> models;
120+ UnityMenuModel* parent = m_model;
121+ UnityMenuModel* child = m_model;
124+ // submenus aren't immediate
125+ bool rows = waitFor([child, subMenuCount]() { return child->rowCount() == subMenuCount; }, 500);
128+ stack.push(child, subMenuIndex);
132+ child = qobject_cast<UnityMenuModel*>(parent->submenu(subMenuIndex));
135+ QCOMPARE(stack.count(), models.count());
136+ QCOMPARE(stack.count(), menuDepth+1);
137+ while(stack.count() > 0) {
138+ QCOMPARE(stack.pop(), models.takeLast());
142+ void testPopOnRemove_data() {
143+ QTest::addColumn<QString>("test");
144+ QTest::addColumn<int>("menuDepth");
145+ QTest::addColumn<int>("subMenuCount");
146+ QTest::addColumn<int>("subMenuIndex");
147+ QTest::addColumn<int>("removeIndex");
148+ QTest::addColumn<int>("resultCount");
150+ QTest::newRow("removeIndexBefore") << "removeIndexBefore" << 4 << 2 << 1 << 0 << 5;
151+ QTest::newRow("removeCurrentIndex") << "removeCurrentIndex" << 4 << 2 << 0 << 0 << 1;
152+ QTest::newRow("removeIndexAfter") << "removeIndexAfter" << 4 << 2 << 0 << 1 << 5;
155+ void testPopOnRemove()
157+ QFETCH(int, menuDepth);
158+ QFETCH(int, subMenuCount);
159+ QFETCH(int, subMenuIndex);
160+ QFETCH(int, removeIndex);
161+ QFETCH(int, resultCount);
163+ UnityMenuModelStack stack;
165+ UnityMenuModel* parent = m_model;
166+ UnityMenuModel* child = m_model;
169+ // submenus aren't immediate
170+ bool rows = waitFor([child, subMenuCount]() { return child->rowCount() == subMenuCount; }, 1000);
173+ stack.push(child, subMenuIndex);
176+ child = qobject_cast<UnityMenuModel*>(parent->submenu(subMenuIndex));
179+ QCOMPARE(stack.count(), menuDepth+1);
180+ g_menu_remove(m_menu, removeIndex);
182+ waitFor([&stack, resultCount]() { return stack.count() == resultCount; }, 1000);
183+ QCOMPARE(stack.count(), resultCount);
187+ bool waitFor(std::function<bool()> functor, int ms) {
189+ QElapsedTimer timer;
191+ while(!functor() && timer.elapsed() < ms) { QTest::qWait(10); }
194+ guint exportMenuModel(GMenu** menu, GDBusConnection* connection, const QString& object_path, int submenuCount, int depth);
197+ GDBusConnection* m_connection;
202+ UnityMenuModel* m_model;
205+void recuseAddMenu(GMenu* menu, int subMenuCount, int depth_remaining)
207+ for (int i = 0; i < subMenuCount; i ++) {
208+ GMenuItem* item = g_menu_item_new("", NULL);
210+ if (depth_remaining > 0) {
211+ GMenu* submenu = g_menu_new ();
212+ recuseAddMenu(submenu, subMenuCount, depth_remaining-1);
213+ g_menu_item_set_submenu (item, G_MENU_MODEL (submenu));
216+ g_menu_append_item (menu, item);
220+guint UnityMenuModelStackTest::exportMenuModel(GMenu** menu, GDBusConnection* connection, const QString& object_path, int submenuCount, int depth)
223+ recuseAddMenu(*menu, submenuCount, depth);
225+ QByteArray path = object_path.toUtf8();
227+ return g_dbus_connection_export_menu_model (connection, path.constData(), G_MENU_MODEL (*menu), NULL);
231+on_bus_acquired (GDBusConnection *bus, const gchar *, gpointer user_data)
233+ UnityMenuModelStackTest* test = (UnityMenuModelStackTest*)user_data;
234+ test->m_connection = bus;
238+on_name_aquired (GDBusConnection*, const gchar*, gpointer user_data)
240+ UnityMenuModelStackTest* test = (UnityMenuModelStackTest*)user_data;
241+ test->m_connected = true;
242+ test->m_failed = false;
247+on_name_lost (GDBusConnection*, const gchar*, gpointer user_data)
249+ UnityMenuModelStackTest* test = (UnityMenuModelStackTest*)user_data;
250+ test->m_connected = false;
251+ test->m_failed = true;
254+QTEST_GUILESS_MAIN(UnityMenuModelStackTest)
255+#include "unitymenumodelstacktest.moc"