on xenial help sign in
fix tests, add copyright headers
commit2493bd69c260ca9a72d162b50468099213b2345f authorMichael Zanetti <michael.zanetti@canonical.com> dateFri 29 Aug 2014, 14:59 (12 years ago) parent2833057
11 files changed+461−429
plugins/Unity/Launcher/dbusinterface.cpp+23−4 plugins/Unity/Launcher/dbusinterface.h+19 plugins/Unity/Launcher/desktopfilehandler.cpp+19 plugins/Unity/Launcher/desktopfilehandler.h+19 plugins/Unity/Launcher/gsettings.cpp+19 plugins/Unity/Launcher/gsettings.h+19 tests/plugins/Unity/Launcher/CMakeLists.txt+5−6 tests/plugins/Unity/Launcher/gsettings.cpp+40 tests/plugins/Unity/Launcher/gsettings.h+38 tests/plugins/Unity/Launcher/launcherbackendtest.cpp−239 tests/plugins/Unity/Launcher/launchermodeltest.cpp+260−180
plugins/Unity/Launcher/dbusinterface.cpp+23−4
@@ -1,3 +1,22 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
120#include "dbusinterface.h"
221#include "launchermodel.h"
322#include "launcheritem.h"
@@ -19,6 +38,7 @@ DBusInterface::DBusInterface(LauncherModel *parent):
1938 if (!con.registerVirtualObject("/com/canonical/Unity/Launcher", this, QDBusConnection::VirtualObjectRegisterOption::SubPath)) {
2039 qWarning() << "Unable to register launcher object";
2140 }
41+ qDebug() << "DBusInterface set up!";
2242}
2343
2444DBusInterface::~DBusInterface()
@@ -31,7 +51,6 @@ DBusInterface::~DBusInterface()
3151
3252QString DBusInterface::introspect(const QString &path) const
3353{
34− qDebug() << "introspecting" << path;
3554 /* This case we should just list the nodes */
3655 if (path == "/com/canonical/Unity/Launcher/" || path == "/com/canonical/Unity/Launcher") {
3756 QString nodes;
@@ -165,13 +184,13 @@ bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnec
165184 }
166185 } else if (message.member() == "Set") {
167186 if (message.arguments()[1].toString() == "count") {
168− int newCount = message.arguments()[2].value<QDBusVariant>().variant().toInt();
187+ int newCount = message.arguments()[2].toInt();
169188 if (!item || newCount != item->count()) {
170189 Q_EMIT countChanged(appid, newCount);
171190 emitPropChangedDbus(appid, "count", QVariant(newCount));
172191 }
173192 } else if (message.arguments()[1].toString() == "countVisible") {
174− bool newVisible = message.arguments()[2].value<QDBusVariant>().variant().toBool();
193+ bool newVisible = message.arguments()[2].toBool();
175194 if (!item || newVisible != item->countVisible()) {
176195 Q_EMIT countVisibleChanged(appid, newVisible);
177196 emitPropChangedDbus(appid, "countVisible", newVisible);
@@ -181,7 +200,7 @@ bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnec
181200 if (item) {
182201 QVariantMap all;
183202 all.insert("count", item->count());
184− all.insert("countVisible", item->count());
203+ all.insert("countVisible", item->countVisible());
185204 retval.append(all);
186205 }
187206 } else {
plugins/Unity/Launcher/dbusinterface.h+19
@@ -1,3 +1,22 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
120#include "launcheritem.h"
221
322#include <QDBusVirtualObject>
plugins/Unity/Launcher/desktopfilehandler.cpp+19
@@ -1,3 +1,22 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
120#include "desktopfilehandler.h"
221
322#include <QStringList>
plugins/Unity/Launcher/desktopfilehandler.h+19
@@ -1,3 +1,22 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
120#ifndef DESKTOPFILEHANDLER_H
221#define DESKTOPFILEHANDLER_H
322
plugins/Unity/Launcher/gsettings.cpp+19
@@ -1,3 +1,22 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
120#include "gsettings.h"
221
322#include <QGSettings>
plugins/Unity/Launcher/gsettings.h+19
@@ -1,3 +1,22 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
120#ifndef GSETTINGS_H
221#define GSETTINGS_H
322
tests/plugins/Unity/Launcher/CMakeLists.txt+5−6
@@ -6,7 +6,6 @@ include_directories(
66 ${CMAKE_CURRENT_BINARY_DIR}
77 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
88 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
9− ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend
109 ${GSETTINGS_QT_INCLUDE_DIRS}
1110 )
1211
@@ -15,17 +14,17 @@ add_definitions(-DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
1514add_definitions(-DLAUNCHER_TESTING)
1615
1716### LauncherModelTest
18−set(testModelCommand ${CMAKE_CURRENT_BINARY_DIR}/launchermodeltestExec
19− -o ${CMAKE_BINARY_DIR}/launchermodeltest.xml,xunitxml
20− -o -,txt)
17+set(testModelCommand dbus-test-runner --task ${CMAKE_CURRENT_BINARY_DIR}/launchermodeltestExec
18+ --parameter -o --parameter ${CMAKE_BINARY_DIR}/launchermodeltest.xml,xunitxml
19+ --parameter -o --parameter -,txt)
2120add_test(NAME launchermodeltest COMMAND ${testModelCommand})
2221add_custom_target(launchermodeltest ${testModelCommand})
2322add_executable(launchermodeltestExec
2423 launchermodeltest.cpp
24+ gsettings.cpp
2525 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launchermodel.cpp
2626 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launcheritem.cpp
2727 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistmodel.cpp
28− ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/gsettings.cpp
2928 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/dbusinterface.cpp
3029 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/desktopfilehandler.cpp
3130 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistentry.cpp
@@ -36,7 +35,7 @@ add_executable(launchermodeltestExec
3635 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
3736 )
3837target_link_libraries(launchermodeltestExec ${GSETTINGS_QT_LDFLAGS})
39−qt5_use_modules(launchermodeltestExec Test Core DBus)
38+qt5_use_modules(launchermodeltestExec Test Core DBus Xml)
4039
4140# copy .desktop files into build directory for shadow builds
4241file(GLOB DESKTOP_FILES *.desktop)
tests/plugins/Unity/Launcher/gsettings.cppnew file+40
@@ -0,0 +1,40 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "gsettings.h"
21+
22+#include <QDebug>
23+
24+// This is a mock implementation to not touch GSettings for real during tests
25+
26+GSettings::GSettings(QObject *parent):
27+ QObject(parent)
28+{
29+
30+}
31+
32+QStringList GSettings::storedApplications() const
33+{
34+ return QStringList();
35+}
36+
37+void GSettings::setStoredApplications(const QStringList &storedApplications)
38+{
39+ Q_UNUSED(storedApplications)
40+}
tests/plugins/Unity/Launcher/gsettings.hnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef GSETTINGS_H
21+#define GSETTINGS_H
22+
23+#include <QObject>
24+#include <QStringList>
25+
26+// This is a mock implementation to not touch GSettings for real during tests
27+
28+class GSettings: public QObject
29+{
30+ Q_OBJECT
31+public:
32+ GSettings(QObject *parent = nullptr);
33+
34+ QStringList storedApplications() const;
35+ void setStoredApplications(const QStringList &storedApplications);
36+};
37+
38+#endif
tests/plugins/Unity/Launcher/launcherbackendtest.cppdeleted−239
@@ -1,239 +0,0 @@
1−/*
2− * Copyright 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 Lesser 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 Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors:
17− * Michael Terry <michael.terry@canonical.com>
18− */
19−
20−#include "launcherbackend.h"
21−
22−#include <QtTest>
23−#include <QDBusConnection>
24−#include <QDBusMessage>
25−#include <QDBusVariant>
26−
27−
28−class LauncherBackendTest : public QObject
29−{
30− Q_OBJECT
31−
32−private Q_SLOTS:
33−
34− void initTestCase()
35− {
36− // As we want to test absolute file paths in the .desktop file, we need to modify the
37− // sample file and replace the path in there with the current build dir.
38− QSettings settings(QDir::currentPath() + "/click-icon.desktop", QSettings::IniFormat);
39− settings.setValue("Desktop Entry/Path", QDir::currentPath());
40− }
41−
42− void testFileNames()
43− {
44− LauncherBackend backend;
45−
46− backend.setStoredApplications(QStringList() << "rel-icon" << "abs-icon" << "invalid");
47− QCOMPARE(backend.storedApplications(), QStringList() << "rel-icon" << "abs-icon");
48− }
49−
50− void testIcon_data() {
51− QTest::addColumn<QString>("appId");
52− QTest::addColumn<QString>("expectedIcon");
53−
54− // Needs to expand a relative icon to the absolute path
55− QTest::newRow("relative icon path") << "rel-icon" << QDir::currentPath() + "/rel-icon.svg";
56−
57− // In case an icon is not found on disk, it needs to fallback on image://theme/ for it
58− QTest::newRow("fallback on theme") << "abs-icon" << "image://theme//path/to/icon.png";
59−
60− // Click packages have a relative icon path but an absolute path as a separate entry
61− QTest::newRow("click package icon") << "click-icon" << QDir::currentPath() + "/click-icon.svg";
62− }
63−
64− void testIcon() {
65− QFETCH(QString, appId);
66− QFETCH(QString, expectedIcon);
67−
68− LauncherBackend backend;
69− backend.setStoredApplications(QStringList() << appId);
70−
71− QCOMPARE(backend.icon(appId), expectedIcon);
72− }
73−
74− void testGetItem_data() {
75− QTest::addColumn<QString>("appId");
76− QTest::addColumn<bool>("exists");
77−
78− QTest::newRow("Exists") << "rel-icon" << true;
79− QTest::newRow("Doesn't Exist") << "does-not-exist" << false;
80− }
81−
82− void testGetItem() {
83− QFETCH(QString, appId);
84− QFETCH(bool, exists);
85−
86− LauncherBackend backend;
87− auto item = backend.getItem(appId);
88−
89− if (exists) {
90− QVERIFY(item != nullptr);
91− } else {
92− QVERIFY(item == nullptr);
93− }
94− }
95−
96−// void testCount_data() {
97−// QTest::addColumn<QString>("appId");
98−// QTest::addColumn<bool>("setCount");
99−// QTest::addColumn<int>("inCount");
100−// QTest::addColumn<bool>("countVisible");
101−// QTest::addColumn<int>("expectedCount");
102−
103−// /* Get baseline data on things working */
104−// QTest::newRow("Baseline") << "rel-icon" << false << 0 << false << -1;
105−
106−// /* Valid count, but not visible */
107−// QTest::newRow("Not visible") << "rel-icon" << true << 42 << false << -1;
108−
109−// /* Turn it on */
110−// QTest::newRow("Visible Count") << "rel-icon" << true << 42 << true << 42;
111−
112−// /* Invalide app to load */
113−// QTest::newRow("Invalid App ID") << "this-app-doesnt-exist" << true << 42 << true << -1;
114−// }
115−
116−// void testCount() {
117−// QFETCH(QString, appId);
118−// QFETCH(bool, setCount);
119−// QFETCH(int, inCount);
120−// QFETCH(bool, countVisible);
121−// QFETCH(int, expectedCount);
122−
123−// LauncherBackend backend;
124−
125−// if (setCount)
126−// backend.setCount(appId, inCount);
127−// backend.setCountVisible(appId, countVisible);
128−
129−// QCOMPARE(backend.count(appId), expectedCount);
130−// }
131−
132−// void testDbusName_data() {
133−// QTest::addColumn<QString>("decoded");
134−// QTest::addColumn<QString>("encoded");
135−
136−// /* Passthrough test */
137−// QTest::newRow("Passthrough") << "fine" << "fine";
138−
139−// /* Number as first characeter */
140−// QTest::newRow("Number first") << "31337" << "_331337";
141−
142−// /* Underscore test */
143−// QTest::newRow("Underscore test") << "this_is_c_style_namespacing" << "this_5Fis_5Fc_5Fstyle_5Fnamespacing";
144−
145−// /* Hyphen test */
146−// QTest::newRow("Hyphen test") << "typical-application" << "typical_2Dapplication";
147−
148−// /* Japanese test */
149−// QTest::newRow("日本語 test") << "日本語" << "_E6_97_A5_E6_9C_AC_E8_AA_9E";
150−// }
151−
152−// void testDbusName() {
153−// QFETCH(QString, decoded);
154−// QFETCH(QString, encoded);
155−
156−// QString encodeOut = LauncherBackend::encodeAppId(decoded);
157−// QCOMPARE(encoded, encodeOut);
158−
159−// QString decodeOut = LauncherBackend::decodeAppId(encoded);
160−// QCOMPARE(decoded, decodeOut);
161−// }
162−
163−// void testDbusIface_data() {
164−// QTest::addColumn<QString>("appId");
165−// QTest::addColumn<bool>("setCount");
166−// QTest::addColumn<int>("inCount");
167−// QTest::addColumn<bool>("countVisible");
168−// QTest::addColumn<int>("expectedCount");
169−
170−// /* Get baseline data on things working */
171−// QTest::newRow("Baseline") << "rel-icon" << false << 0 << false << -1;
172−
173−// /* Turn it on */
174−// QTest::newRow("Visible Count") << "rel-icon" << true << 42 << true << 42;
175−
176−// /* Invalide app to load */
177−// QTest::newRow("Invalid App ID") << "this-app-doesnt-exist" << true << 42 << true << -1;
178−// }
179−
180−// void testDbusIface() {
181−// QFETCH(QString, appId);
182−// QFETCH(bool, setCount);
183−// QFETCH(int, inCount);
184−// QFETCH(bool, countVisible);
185−// QFETCH(int, expectedCount);
186−
187−// QDBusConnection con = QDBusConnection::sessionBus();
188−// QDBusMessage message;
189−// QDBusMessage reply;
190−
191−// LauncherBackend backend;
192−
193−// if (setCount) {
194−// message = QDBusMessage::createMethodCall("com.canonical.Unity.Launcher",
195−// "/com/canonical/Unity/Launcher/" + LauncherBackend::encodeAppId(appId),
196−// "org.freedesktop.DBus.Properties",
197−// "Set");
198−// QVariantList cargs;
199−// cargs.append(QString("com.canonical.Unity.Launcher.Item"));
200−// cargs.append(QString("count"));
201−// cargs.append(QVariant::fromValue(QDBusVariant(inCount)));
202−
203−// message.setArguments(cargs);
204−// reply = con.call(message);
205−// QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
206−// }
207−
208−// /* Set countVisible */
209−// message = QDBusMessage::createMethodCall("com.canonical.Unity.Launcher",
210−// "/com/canonical/Unity/Launcher/" + LauncherBackend::encodeAppId(appId),
211−// "org.freedesktop.DBus.Properties",
212−// "Set");
213−// QVariantList cvargs;
214−// cvargs.append(QString("com.canonical.Unity.Launcher.Item"));
215−// cvargs.append(QString("countVisible"));
216−// cvargs.append(QVariant::fromValue(QDBusVariant(countVisible)));
217−
218−// message.setArguments(cvargs);
219−// reply = con.call(message);
220−// QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
221−
222−// /* Get value */
223−// message = QDBusMessage::createMethodCall("com.canonical.Unity.Launcher",
224−// "/com/canonical/Unity/Launcher/" + LauncherBackend::encodeAppId(appId),
225−// "org.freedesktop.DBus.Properties",
226−// "Get");
227−// QVariantList getargs;
228−// getargs.append(QString("com.canonical.Unity.Launcher.Item"));
229−// getargs.append(QString("count"));
230−
231−// message.setArguments(getargs);
232−// reply = con.call(message);
233−// QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
234−// QCOMPARE(reply.arguments()[0].value<QDBusVariant>().variant().toInt(), expectedCount);
235−// }
236−};
237−
238−QTEST_GUILESS_MAIN(LauncherBackendTest)
239−#include "launcherbackendtest.moc"
tests/plugins/Unity/Launcher/launchermodeltest.cpp+260−180
@@ -23,8 +23,12 @@
2323
2424#include "launcheritem.h"
2525#include "launchermodel.h"
26+#include "dbusinterface.h"
2627
2728#include <QtTest>
29+#include <QDBusInterface>
30+#include <QDBusReply>
31+#include <QDomDocument>
2832
2933// This is a mock, specifically to test the LauncherModel
3034class MockApp: public unity::shell::application::ApplicationInfoInterface
@@ -111,186 +115,262 @@ private:
111115
112116private Q_SLOTS:
113117
114−// void initTestCase() {
115−// launcherModel = new LauncherModel(this);
116−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
117−
118−// appManager = new MockAppManager(this);
119−// launcherModel->setApplicationManager(appManager);
120−// }
121−
122−// // Adding 2 apps to the mock appmanager. Both should appear in the launcher.
123−// void init() {
124−// appManager->addApplication(new MockApp("abs-icon"));
125−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
126−
127−// appManager->addApplication(new MockApp("no-icon"));
128−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
129−// }
130−
131−// // Removing apps from appmanager and launcher as pinned ones would stick
132−// void cleanup() {
133−// while (appManager->count() > 0) {
134−// appManager->removeApplication(0);
135−// }
136−// while (launcherModel->rowCount(QModelIndex()) > 0) {
137−// launcherModel->requestRemove(launcherModel->get(0)->appId());
138−// }
139−// }
140−
141−// void testMove() {
142−// QCOMPARE(launcherModel->get(0)->pinned(), false);
143−// QCOMPARE(launcherModel->get(1)->pinned(), false);
144−
145−// LauncherItemInterface *item0BeforeMove = launcherModel->get(0);
146−// LauncherItemInterface *item1BeforeMove = launcherModel->get(1);
147−// launcherModel->move(1, 0);
148−
149−// QCOMPARE(item0BeforeMove, launcherModel->get(1));
150−// QCOMPARE(item1BeforeMove, launcherModel->get(0));
151−
152−// // moved item must be pinned now
153−// QCOMPARE(item0BeforeMove->pinned(), false);
154−// QCOMPARE(item1BeforeMove->pinned(), true);
155−// }
156−
157−// void testPinning() {
158−// QSignalSpy spy(launcherModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
159−// QCOMPARE(launcherModel->get(0)->pinned(), false);
160−// QCOMPARE(launcherModel->get(1)->pinned(), false);
161−// launcherModel->pin(launcherModel->get(0)->appId());
162−// QCOMPARE(launcherModel->get(0)->pinned(), true);
163−// QCOMPARE(launcherModel->get(1)->pinned(), false);
164−// QCOMPARE(spy.count(), 1);
165−// QCOMPARE(spy.at(0).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
166−
167−// launcherModel->requestRemove(launcherModel->get(0)->appId());
168−// QCOMPARE(launcherModel->get(0)->pinned(), false);
169−// QCOMPARE(launcherModel->get(1)->pinned(), false);
170−// QCOMPARE(spy.count(), 2);
171−// QCOMPARE(spy.at(1).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
172−// }
173−
174−// void testRemove_data() {
175−
176−// QTest::addColumn<bool>("pinned");
177−// QTest::addColumn<bool>("running");
178−
179−// QTest::newRow("non-pinned, running") << false << true;
180−// QTest::newRow("pinned, running") << true << false;
181−// QTest::newRow("pinned, non-running") << true << false;
182−// }
183−
184−// void testRemove() {
185−// QFETCH(bool, pinned);
186−// QFETCH(bool, running);
187−
188−// // In the beginning we always have two items
189−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
190−
191−// // pin one if required
192−// if (pinned) {
193−// launcherModel->pin(launcherModel->get(1)->appId());
194−// }
195−
196−// // stop it if required
197−// if (!running) {
198−// appManager->removeApplication(1);
199−// }
200−
201−// // Now remove it
202−// launcherModel->requestRemove(launcherModel->get(1)->appId());
203−
204−// if (running) {
205−// // both apps are running, both apps must still be here
206−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
207−
208−// // Item must be unpinned now
209−// QCOMPARE(launcherModel->get(1)->pinned(), false);
210−
211−// } else if (pinned) {
212−// // Item 1 must go away, item 0 is here to stay
213−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
214−// }
215−
216−// // done our checks. now stop the app if was still running
217−// if (running) {
218−// appManager->removeApplication(1);
219−// }
220−
221−// // It needs to go away in any case now
222−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
223−// }
224−
225−// void testQuickListPinningRemoving() {
226−// // we start with 2 unpinned items
227−// QCOMPARE(launcherModel->get(0)->pinned(), false);
228−// QCOMPARE(launcherModel->get(1)->pinned(), false);
229−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
230−
231−// // find the Pin item in the quicklist
232−// QuickListModel *model = qobject_cast<QuickListModel*>(launcherModel->get(0)->quickList());
233−// int pinActionIndex = -1;
234−// for (int i = 0; i < model->rowCount(QModelIndex()); ++i) {
235−// if (model->get(i).actionId() == "pin_item") {
236−// pinActionIndex = i;
237−// break;
238−// }
239−// }
240−// QVERIFY(pinActionIndex >= 0);
241−
242−// // trigger pin item quicklist action => Item must be pinned now.
243−// launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
244−// QCOMPARE(launcherModel->get(0)->pinned(), true);
245−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
246−
247−// // quicklist needs to transform to remove item. trigger it and check it item goes away
248−// launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
249−// QCOMPARE(launcherModel->get(0)->pinned(), false);
250−
251−// // still needs to be here as the app is still here
252−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
253−// // close the app
254−// appManager->removeApplication(0);
255−// // Now it needs to go away
256−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
257−// }
258−
259−// void testApplicationFocused() {
260−// // all apps unfocused at beginning...
261−// QCOMPARE(launcherModel->get(0)->focused(), false);
262−// QCOMPARE(launcherModel->get(1)->focused(), false);
263−
264−// appManager->focusApplication("abs-icon");
265−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
266−// QCOMPARE(launcherModel->get(0)->focused(), true);
267−// QCOMPARE(launcherModel->get(1)->focused(), false);
268−
269−// appManager->focusApplication("no-icon");
270−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
271−// QCOMPARE(launcherModel->get(0)->focused(), false);
272−// QCOMPARE(launcherModel->get(1)->focused(), true);
273−// }
274−
275−// void testClosingApps() {
276−// // At the start there are 2 items. Let's pin one.
277−// launcherModel->pin("abs-icon");
278−// while (appManager->count() > 0) {
279−// appManager->removeApplication(0);
280−// }
281−// // The pinned one needs to stay, the other needs to disappear
282−// QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
283−// QCOMPARE(launcherModel->get(0)->appId(), QLatin1String("abs-icon"));
284−// }
285−
286−// void testGetUrlForAppId() {
287−// QCOMPARE(launcherModel->getUrlForAppId(QString()), QString());
288−// QCOMPARE(launcherModel->getUrlForAppId(""), QString());
289−// QCOMPARE(launcherModel->getUrlForAppId("no-name"), QString("application:///no-name.desktop"));
290−// QCOMPARE(launcherModel->getUrlForAppId("com.test.good"), QString("appid://com.test.good/first-listed-app/current-user-version"));
291−// QCOMPARE(launcherModel->getUrlForAppId("com.test.good_application"), QString("appid://com.test.good/application/current-user-version"));
292−// QCOMPARE(launcherModel->getUrlForAppId("com.test.good_application_1.2.3"), QString("appid://com.test.good/application/current-user-version"));
293−// }
118+ void initTestCase() {
119+ launcherModel = new LauncherModel(this);
120+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
121+
122+ appManager = new MockAppManager(this);
123+ launcherModel->setApplicationManager(appManager);
124+ }
125+
126+ // Adding 2 apps to the mock appmanager. Both should appear in the launcher.
127+ void init() {
128+ appManager->addApplication(new MockApp("abs-icon"));
129+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
130+
131+ appManager->addApplication(new MockApp("no-icon"));
132+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
133+ }
134+
135+ // Removing apps from appmanager and launcher as pinned ones would stick
136+ void cleanup() {
137+ while (appManager->count() > 0) {
138+ appManager->removeApplication(0);
139+ }
140+ while (launcherModel->rowCount(QModelIndex()) > 0) {
141+ launcherModel->requestRemove(launcherModel->get(0)->appId());
142+ }
143+ }
144+
145+ void testMove() {
146+ QCOMPARE(launcherModel->get(0)->pinned(), false);
147+ QCOMPARE(launcherModel->get(1)->pinned(), false);
148+
149+ LauncherItemInterface *item0BeforeMove = launcherModel->get(0);
150+ LauncherItemInterface *item1BeforeMove = launcherModel->get(1);
151+ launcherModel->move(1, 0);
152+
153+ QCOMPARE(item0BeforeMove, launcherModel->get(1));
154+ QCOMPARE(item1BeforeMove, launcherModel->get(0));
155+
156+ // moved item must be pinned now
157+ QCOMPARE(item0BeforeMove->pinned(), false);
158+ QCOMPARE(item1BeforeMove->pinned(), true);
159+ }
160+
161+ void testPinning() {
162+ QSignalSpy spy(launcherModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
163+ QCOMPARE(launcherModel->get(0)->pinned(), false);
164+ QCOMPARE(launcherModel->get(1)->pinned(), false);
165+ launcherModel->pin(launcherModel->get(0)->appId());
166+ QCOMPARE(launcherModel->get(0)->pinned(), true);
167+ QCOMPARE(launcherModel->get(1)->pinned(), false);
168+ QCOMPARE(spy.count(), 1);
169+ QCOMPARE(spy.at(0).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
170+
171+ launcherModel->requestRemove(launcherModel->get(0)->appId());
172+ QCOMPARE(launcherModel->get(0)->pinned(), false);
173+ QCOMPARE(launcherModel->get(1)->pinned(), false);
174+ QCOMPARE(spy.count(), 2);
175+ QCOMPARE(spy.at(1).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
176+ }
177+
178+ void testRemove_data() {
179+
180+ QTest::addColumn<bool>("pinned");
181+ QTest::addColumn<bool>("running");
182+
183+ QTest::newRow("non-pinned, running") << false << true;
184+ QTest::newRow("pinned, running") << true << false;
185+ QTest::newRow("pinned, non-running") << true << false;
186+ }
187+
188+ void testRemove() {
189+ QFETCH(bool, pinned);
190+ QFETCH(bool, running);
191+
192+ // In the beginning we always have two items
193+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
194+
195+ // pin one if required
196+ if (pinned) {
197+ launcherModel->pin(launcherModel->get(1)->appId());
198+ }
199+
200+ // stop it if required
201+ if (!running) {
202+ appManager->removeApplication(1);
203+ }
204+
205+ // Now remove it
206+ launcherModel->requestRemove(launcherModel->get(1)->appId());
207+
208+ if (running) {
209+ // both apps are running, both apps must still be here
210+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
211+
212+ // Item must be unpinned now
213+ QCOMPARE(launcherModel->get(1)->pinned(), false);
214+
215+ } else if (pinned) {
216+ // Item 1 must go away, item 0 is here to stay
217+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
218+ }
219+
220+ // done our checks. now stop the app if was still running
221+ if (running) {
222+ appManager->removeApplication(1);
223+ }
224+
225+ // It needs to go away in any case now
226+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
227+ }
228+
229+ void testQuickListPinningRemoving() {
230+ // we start with 2 unpinned items
231+ QCOMPARE(launcherModel->get(0)->pinned(), false);
232+ QCOMPARE(launcherModel->get(1)->pinned(), false);
233+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
234+
235+ // find the Pin item in the quicklist
236+ QuickListModel *model = qobject_cast<QuickListModel*>(launcherModel->get(0)->quickList());
237+ int pinActionIndex = -1;
238+ for (int i = 0; i < model->rowCount(QModelIndex()); ++i) {
239+ if (model->get(i).actionId() == "pin_item") {
240+ pinActionIndex = i;
241+ break;
242+ }
243+ }
244+ QVERIFY(pinActionIndex >= 0);
245+
246+ // trigger pin item quicklist action => Item must be pinned now.
247+ launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
248+ QCOMPARE(launcherModel->get(0)->pinned(), true);
249+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
250+
251+ // quicklist needs to transform to remove item. trigger it and check it item goes away
252+ launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
253+ QCOMPARE(launcherModel->get(0)->pinned(), false);
254+
255+ // still needs to be here as the app is still here
256+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
257+ // close the app
258+ appManager->removeApplication(0);
259+ // Now it needs to go away
260+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
261+ }
262+
263+ void testApplicationFocused() {
264+ // all apps unfocused at beginning...
265+ QCOMPARE(launcherModel->get(0)->focused(), false);
266+ QCOMPARE(launcherModel->get(1)->focused(), false);
267+
268+ appManager->focusApplication("abs-icon");
269+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
270+ QCOMPARE(launcherModel->get(0)->focused(), true);
271+ QCOMPARE(launcherModel->get(1)->focused(), false);
272+
273+ appManager->focusApplication("no-icon");
274+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
275+ QCOMPARE(launcherModel->get(0)->focused(), false);
276+ QCOMPARE(launcherModel->get(1)->focused(), true);
277+ }
278+
279+ void testClosingApps() {
280+ // At the start there are 2 items. Let's pin one.
281+ launcherModel->pin("abs-icon");
282+ while (appManager->count() > 0) {
283+ appManager->removeApplication(0);
284+ }
285+ // The pinned one needs to stay, the other needs to disappear
286+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
287+ QCOMPARE(launcherModel->get(0)->appId(), QLatin1String("abs-icon"));
288+ }
289+
290+ void testGetUrlForAppId() {
291+ QCOMPARE(launcherModel->getUrlForAppId(QString()), QString());
292+ QCOMPARE(launcherModel->getUrlForAppId(""), QString());
293+ QCOMPARE(launcherModel->getUrlForAppId("no-name"), QString("application:///no-name.desktop"));
294+ QCOMPARE(launcherModel->getUrlForAppId("com.test.good"), QString("application:///com.test.good.desktop"));
295+ QCOMPARE(launcherModel->getUrlForAppId("com.test.good_application"), QString("appid://com.test.good/application/current-user-version"));
296+ QCOMPARE(launcherModel->getUrlForAppId("com.test.good_application_1.2.3"), QString("appid://com.test.good/application/current-user-version"));
297+ }
298+
299+ void testIntrospection() {
300+ QDBusInterface interface("com.canonical.Unity.Launcher", "/com/canonical/Unity/Launcher", "org.freedesktop.DBus.Introspectable");
301+ QDBusReply<QString> reply = interface.call("Introspect");
302+ QStringList nodes = extractNodes(reply.value());
303+ QCOMPARE(nodes.count(), launcherModel->rowCount());
304+
305+ appManager->addApplication(new MockApp("foobar"));
306+ reply = interface.call("Introspect");
307+ nodes = extractNodes(reply.value());
308+ QCOMPARE(nodes.contains("foobar"), true);
309+
310+ appManager->removeApplication(2);
311+ reply = interface.call("Introspect");
312+ nodes = extractNodes(reply.value());
313+ QCOMPARE(nodes.contains("foobar"), false);
314+ }
315+
316+ QStringList extractNodes(const QString &introspectionXml) {
317+ QXmlStreamReader introspectReply(introspectionXml);
318+
319+ QStringList ret;
320+ while (!introspectReply.atEnd() && !introspectReply.hasError()) {
321+ QXmlStreamReader::TokenType token = introspectReply.readNext();
322+
323+ if (token == QXmlStreamReader::StartElement) {
324+ if (introspectReply.name() == "node" && introspectReply.attributes().count() > 0) {
325+ ret << introspectReply.attributes().value("name").toString();
326+ }
327+ }
328+ }
329+ return ret;
330+ }
331+
332+ void testCountEmblems() {
333+ // Call GetAll on abs-icon
334+ QDBusInterface interface("com.canonical.Unity.Launcher", "/com/canonical/Unity/Launcher/abs_2Dicon", "org.freedesktop.DBus.Properties");
335+ QDBusReply<QVariantMap> reply = interface.call("GetAll");
336+ QVariantMap map = reply.value();
337+
338+ // Make sure GetAll returns a map with count and countVisible props
339+ QCOMPARE(map.contains("count"), true);
340+ QCOMPARE(map.contains("countVisible"), true);
341+
342+ // Make sure count is intitilized to 0 and non-visible
343+ QCOMPARE(map.value("count").toInt(), 0);
344+ QCOMPARE(map.value("countVisible").toBool(), false);
345+
346+ // Now make it visible and set it to 55 through D-Bus
347+ interface.call("Set", "com.canonical.Unity.Launcher.Item", "count", 55);
348+ interface.call("Set", "com.canonical.Unity.Launcher.Item", "countVisible", true);
349+
350+ // Fetch it again using GetAll
351+ reply = interface.call("GetAll");
352+ map = reply.value();
353+
354+ // Make sure values have changed on the D-Bus interface
355+ QCOMPARE(map.value("count").toInt(), 55);
356+ QCOMPARE(map.value("countVisible").toBool(), true);
357+
358+ // Now the item on the upper side of the API
359+ int index = launcherModel->findApplication("abs-icon");
360+ QCOMPARE(index >= 0, true);
361+
362+ // And make sure values have changed there as well
363+ QCOMPARE(launcherModel->get(index)->countVisible(), true);
364+ QCOMPARE(launcherModel->get(index)->count(), 55);
365+ }
366+
367+ void testRefresh() {
368+ QDBusInterface interface("com.canonical.Unity.Launcher", "/com/canonical/Unity/Launcher", "com.canonical.Unity.Launcher");
369+ QDBusReply<void> reply = interface.call("Refresh");
370+
371+ // Make sure the call to Refresh returned without error.
372+ QCOMPARE(reply.isValid(), true);
373+ }
294374};
295375
296376QTEST_GUILESS_MAIN(LauncherModelTest)