on xenial help sign in
Make a few DBus calls asynchronous, for a smoother UX.
941e4b7Michael Terry
plugins/AccountsService/AccountsService.cpp+3−3
@@ -74,7 +74,7 @@ void AccountsService::setDemoEdges(bool demoEdges)
74{
74{
75 if (m_demoEdges != demoEdges) {
75 if (m_demoEdges != demoEdges) {
76 m_demoEdges = demoEdges;
76 m_demoEdges = demoEdges;
77− m_service->setUserProperty(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
77+ m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("demo-edges"), demoEdges);
78
78
79 Q_EMIT demoEdgesChanged();
79 Q_EMIT demoEdgesChanged();
80 }
80 }
@@ -114,7 +114,7 @@ void AccountsService::setHereEnabled(bool enabled)
114{
114{
115 if (m_hereEnabled != enabled) {
115 if (m_hereEnabled != enabled) {
116 m_hereEnabled = enabled;
116 m_hereEnabled = enabled;
117− m_service->setUserProperty(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
117+ m_service->setUserPropertyAsync(m_user, QStringLiteral("com.ubuntu.location.providers.here.AccountsService"), QStringLiteral("LicenseAccepted"), enabled);
118
118
119 Q_EMIT hereEnabledChanged();
119 Q_EMIT hereEnabledChanged();
120 }
120 }
@@ -403,7 +403,7 @@ void AccountsService::setFailedLogins(uint failedLogins)
403{
403{
404 if (m_failedLogins != failedLogins) {
404 if (m_failedLogins != failedLogins) {
405 m_failedLogins = failedLogins;
405 m_failedLogins = failedLogins;
406− m_service->setUserProperty(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
406+ m_service->setUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService.Private"), QStringLiteral("FailedLogins"), failedLogins);
407
407
408 Q_EMIT failedLoginsChanged();
408 Q_EMIT failedLoginsChanged();
409 }
409 }
plugins/AccountsService/AccountsServiceDBusAdaptor.cpp+1−22
@@ -37,18 +37,6 @@ AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
37 connection, this);
37 connection, this);
38}
38}
39
39
40−QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
41−{
42− QDBusInterface *iface = getUserInterface(user);
43− if (iface != nullptr && iface->isValid()) {
44− QDBusReply<QVariant> answer = iface->call(QStringLiteral("Get"), interface, property);
45− if (answer.isValid()) {
46− return answer;
47− }
48− }
49− return QVariant();
50−}
51−
52QDBusPendingReply<QVariant> AccountsServiceDBusAdaptor::getUserPropertyAsync(const QString &user, const QString &interface, const QString &property)
40QDBusPendingReply<QVariant> AccountsServiceDBusAdaptor::getUserPropertyAsync(const QString &user, const QString &interface, const QString &property)
53{
41{
54 QDBusInterface *iface = getUserInterface(user);
42 QDBusInterface *iface = getUserInterface(user);
@@ -58,15 +46,6 @@ QDBusPendingReply<QVariant> AccountsServiceDBusAdaptor::getUserPropertyAsync(con
58 return QDBusPendingReply<QVariant>(QDBusMessage::createError(QDBusError::Other, QStringLiteral("Invalid Interface")));
46 return QDBusPendingReply<QVariant>(QDBusMessage::createError(QDBusError::Other, QStringLiteral("Invalid Interface")));
59}
47}
60
48
61−void AccountsServiceDBusAdaptor::setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value)
62−{
63− QDBusInterface *iface = getUserInterface(user);
64− if (iface != nullptr && iface->isValid()) {
65− // The value needs to be carefully wrapped
66− iface->call(QStringLiteral("Set"), interface, property, QVariant::fromValue(QDBusVariant(value)));
67− }
68−}
69−
70QDBusPendingCall AccountsServiceDBusAdaptor::setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value)
49QDBusPendingCall AccountsServiceDBusAdaptor::setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value)
71{
50{
72 QDBusInterface *iface = getUserInterface(user);
51 QDBusInterface *iface = getUserInterface(user);
@@ -116,7 +95,7 @@ QDBusInterface *AccountsServiceDBusAdaptor::getUserInterface(const QString &user
116{
95{
117 QDBusInterface *iface = m_users.value(user);
96 QDBusInterface *iface = m_users.value(user);
118 if (iface == nullptr && m_accountsManager->isValid()) {
97 if (iface == nullptr && m_accountsManager->isValid()) {
119− QDBusReply<QDBusObjectPath> answer = m_accountsManager->asyncCall(QStringLiteral("FindUserByName"), user);
98+ QDBusReply<QDBusObjectPath> answer = m_accountsManager->call(QStringLiteral("FindUserByName"), user);
120 if (answer.isValid()) {
99 if (answer.isValid()) {
121 const QString path = answer.value().path();
100 const QString path = answer.value().path();
122
101
plugins/AccountsService/AccountsServiceDBusAdaptor.h−12
@@ -35,19 +35,7 @@ public:
35 explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
35 explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
36 ~AccountsServiceDBusAdaptor() = default;
36 ~AccountsServiceDBusAdaptor() = default;
37
37
38− Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
39 Q_INVOKABLE QDBusPendingReply<QVariant> getUserPropertyAsync(const QString &user, const QString &interface, const QString &property);
38 Q_INVOKABLE QDBusPendingReply<QVariant> getUserPropertyAsync(const QString &user, const QString &interface, const QString &property);
40−
41− template <typename T>
42− inline T getUserProperty(const QString &user, const QString &interface, const QString &property) {
43− const QVariant variant = getUserProperty(user, interface, property);
44− if (variant.isValid() && variant.canConvert<QDBusArgument>()) {
45− return qdbus_cast<T>(variant.value<QDBusArgument>());
46− }
47− return T();
48− }
49−
50− Q_INVOKABLE void setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value);
51 Q_INVOKABLE QDBusPendingCall setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
39 Q_INVOKABLE QDBusPendingCall setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
52
40
53Q_SIGNALS:
41Q_SIGNALS:
plugins/Greeter/Unity/Launcher/launchermodelas.cpp+19−4
@@ -194,15 +194,30 @@ int LauncherModel::findApplication(const QString &appId)
194 return -1;
194 return -1;
195}
195}
196
196
197−typedef QList<QVariantMap> VariantMapList;
198void LauncherModel::refresh()
197void LauncherModel::refresh()
199{
198{
199+ if (!m_accounts || m_user.isEmpty()) {
200− QList<QVariantMap> items;
200+ refreshWithItems(QList<QVariantMap>());
201+ } else {
202+ QDBusPendingCall pendingCall = m_accounts->getUserPropertyAsync(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("LauncherItems"));
203+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
204+ connect(watcher, &QDBusPendingCallWatcher::finished,
205+ this, [this](QDBusPendingCallWatcher* watcher) {
206+
207+ QDBusPendingReply<QVariant> reply = *watcher;
208+ watcher->deleteLater();
209+ if (reply.isError()) {
210+ qWarning() << "Failed to refresh LauncherItems" << reply.error().message();
211+ return;
212+ }
201
213
202− if (m_accounts && !m_user.isEmpty()) {
214+ refreshWithItems(qdbus_cast<QList<QVariantMap>>(reply.value().value<QDBusArgument>()));
203− items = m_accounts->getUserProperty<VariantMapList>(m_user, QStringLiteral("com.canonical.unity.AccountsService"), QStringLiteral("LauncherItems"));
215+ });
204 }
216 }
217+}
205
218
219+void LauncherModel::refreshWithItems(const QList<QVariantMap> &items)
220+{
206 // First walk through all the existing items and see if we need to remove something
221 // First walk through all the existing items and see if we need to remove something
207 QList<LauncherItem*> toBeRemoved;
222 QList<LauncherItem*> toBeRemoved;
208
223
plugins/Greeter/Unity/Launcher/launchermodelas.h+2
@@ -65,6 +65,8 @@ private Q_SLOTS:
65 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
65 void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
66
66
67private:
67private:
68+ void refreshWithItems(const QList<QVariantMap> &items);
69+
68 QString m_user;
70 QString m_user;
69 QList<LauncherItem*> m_list;
71 QList<LauncherItem*> m_list;
70 AccountsServiceDBusAdaptor *m_accounts;
72 AccountsServiceDBusAdaptor *m_accounts;
plugins/Unity/Session/dbusunitysessionservice.cpp+64−36
@@ -61,7 +61,7 @@ public:
61 QStringLiteral("GetSessionByPID"));
61 QStringLiteral("GetSessionByPID"));
62 msg << (quint32) getpid();
62 msg << (quint32) getpid();
63
63
64− QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().asyncCall(msg);
64+ QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().call(msg);
65 if (reply.isValid()) {
65 if (reply.isValid()) {
66 logindSessionPath = reply.value().path();
66 logindSessionPath = reply.value().path();
67
67
@@ -92,20 +92,28 @@ public:
92 msg << "Unity"; // who
92 msg << "Unity"; // who
93 msg << "Unity8 handles power events"; // why
93 msg << "Unity8 handles power events"; // why
94 msg << "block"; // mode
94 msg << "block"; // mode
95− QDBusReply<QDBusUnixFileDescriptor> desc = QDBusConnection::systemBus().asyncCall(msg);
96
95
97− if (desc.isValid()) {
96+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
98− m_systemdInhibitFd = desc.value();
97+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
99− } else {
98+ connect(watcher, &QDBusPendingCallWatcher::finished,
99+ this, [this](QDBusPendingCallWatcher* watcher) {
100+
101+ QDBusPendingReply<QDBusUnixFileDescriptor> reply = *watcher;
102+ watcher->deleteLater();
103+ if (reply.isError()) {
100− qWarning() << "failed to inhibit systemd powersave handling";
104+ qWarning() << "Failed to inhibit systemd powersave handling" << reply.error().message();
105+ return;
106+ }
107+
108+ m_systemdInhibitFd = reply.value();
101− }
109+ });
102 }
110 }
103
111
104
112
105 bool checkLogin1Call(const QString &method) const
113 bool checkLogin1Call(const QString &method) const
106 {
114 {
107 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
115 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
108− QDBusReply<QString> reply = QDBusConnection::systemBus().asyncCall(msg);
116+ QDBusReply<QString> reply = QDBusConnection::systemBus().call(msg);
109 return reply.isValid() && (reply == QStringLiteral("yes") || reply == QStringLiteral("challenge"));
117 return reply.isValid() && (reply == QStringLiteral("yes") || reply == QStringLiteral("challenge"));
110 }
118 }
111
119
@@ -119,6 +127,21 @@ public:
119 QDBusConnection::systemBus().asyncCall(msg);
127 QDBusConnection::systemBus().asyncCall(msg);
120 }
128 }
121
129
130+ void setActive(bool active)
131+ {
132+ isSessionActive = active;
133+
134+ Q_EMIT screensaverActiveChanged(!isSessionActive);
135+
136+ if (isSessionActive) {
137+ screensaverActiveTimer.invalidate();
138+ setIdleHint(false);
139+ } else {
140+ screensaverActiveTimer.start();
141+ setIdleHint(true);
142+ }
143+ }
144+
122 void checkActive()
145 void checkActive()
123 {
146 {
124 if (logindSessionPath.isEmpty()) {
147 if (logindSessionPath.isEmpty()) {
@@ -133,12 +156,20 @@ public:
133 msg << LOGIN1_SESSION_IFACE;
156 msg << LOGIN1_SESSION_IFACE;
134 msg << ACTIVE_KEY;
157 msg << ACTIVE_KEY;
135
158
136− QDBusReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(msg);
159+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
160+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
161+ connect(watcher, &QDBusPendingCallWatcher::finished,
162+ this, [this](QDBusPendingCallWatcher* watcher) {
163+
164+ QDBusPendingReply<QVariant> reply = *watcher;
165+ watcher->deleteLater();
137− if (reply.isValid()) {
166+ if (reply.isError()) {
138− isSessionActive = reply.value().toBool();
139− } else {
140− qWarning() << "Failed to get Active property" << reply.error().message();
167+ qWarning() << "Failed to get Active property" << reply.error().message();
168+ return;
169+ }
170+
171+ setActive(reply.value().toBool());
141− }
172+ });
142 }
173 }
143
174
144 quint32 screensaverActiveTime() const
175 quint32 screensaverActiveTime() const
@@ -159,7 +190,7 @@ public:
159 msg << LOGIN1_SESSION_IFACE;
190 msg << LOGIN1_SESSION_IFACE;
160 msg << IDLE_SINCE_KEY;
191 msg << IDLE_SINCE_KEY;
161
192
162− QDBusReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(msg);
193+ QDBusReply<QVariant> reply = QDBusConnection::systemBus().call(msg);
163 if (reply.isValid()) {
194 if (reply.isValid()) {
164 return reply.value().value<quint64>();
195 return reply.value().value<quint64>();
165 } else {
196 } else {
@@ -184,22 +215,10 @@ private Q_SLOTS:
184 {
215 {
185 Q_UNUSED(iface)
216 Q_UNUSED(iface)
186
217
187− if (changedProps.contains(ACTIVE_KEY) || invalidatedProps.contains(ACTIVE_KEY)) {
218+ if (changedProps.contains(ACTIVE_KEY)) {
188− if (changedProps.value(ACTIVE_KEY).isValid()) {
189− isSessionActive = changedProps.value(ACTIVE_KEY).toBool();
219+ setActive(changedProps.value(ACTIVE_KEY).toBool());
190− } else {
220+ } else if (invalidatedProps.contains(ACTIVE_KEY)) {
191− checkActive();
221+ checkActive();
192− }
193−
194− Q_EMIT screensaverActiveChanged(!isSessionActive);
195−
196− if (isSessionActive) {
197− screensaverActiveTimer.invalidate();
198− setIdleHint(false);
199− } else {
200− screensaverActiveTimer.start();
201− setIdleHint(true);
202− }
203 }
222 }
204 }
223 }
205
224
@@ -325,13 +344,22 @@ void DBusUnitySessionService::Lock()
325 sessionPath,
344 sessionPath,
326 QStringLiteral("org.freedesktop.DisplayManager.Session"),
345 QStringLiteral("org.freedesktop.DisplayManager.Session"),
327 QStringLiteral("Lock"));
346 QStringLiteral("Lock"));
347+
328− QDBusReply<void> reply = QDBusConnection::systemBus().asyncCall(msg);
348+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
349+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
350+ connect(watcher, &QDBusPendingCallWatcher::finished,
351+ this, [this](QDBusPendingCallWatcher* watcher) {
352+
353+ QDBusPendingReply<QVariant> reply = *watcher;
354+ watcher->deleteLater();
329− if (!reply.isValid()) {
355+ if (reply.isError()) {
330− qWarning() << "Lock call failed" << reply.error().message();
356+ qWarning() << "Lock call failed" << reply.error().message();
331− } else {
357+ return;
358+ }
359+
332 // emit Locked when the call succeeds
360 // emit Locked when the call succeeds
333 Q_EMIT Locked();
361 Q_EMIT Locked();
334− }
362+ });
335}
363}
336
364
337bool DBusUnitySessionService::IsLocked() const
365bool DBusUnitySessionService::IsLocked() const
tests/plugins/AccountsService/AccountsServer.cpp+11−5
@@ -18,13 +18,14 @@
18 */
18 */
19
19
20#include "AccountsServer.h"
20#include "AccountsServer.h"
21+#include "AccountsUserAdaptor.h"
22+#include "PropertiesAdaptor.h"
21#include "PropertiesServer.h"
23#include "PropertiesServer.h"
22#include <QDBusConnection>
24#include <QDBusConnection>
23#include <QDebug>
25#include <QDebug>
24
26
25−AccountsServer::AccountsServer(PropertiesServer* propServer, QObject *parent)
27+AccountsServer::AccountsServer(QObject *parent)
26 : QObject(parent)
28 : QObject(parent)
27− , m_propServer(propServer)
28{
29{
29}
30}
30
31
@@ -36,16 +37,21 @@ QDBusObjectPath AccountsServer::FindUserByName(const QString &user)
36bool AccountsServer::AddUser(const QString &user)
37bool AccountsServer::AddUser(const QString &user)
37{
38{
38 QString path(QString("/%1").arg(user));
39 QString path(QString("/%1").arg(user));
39− if (QDBusConnection::sessionBus().objectRegisteredAt(path) == m_propServer)
40+ if (QDBusConnection::sessionBus().objectRegisteredAt(path) != nullptr)
40 return true;
41 return true;
42+
43+ auto props = new PropertiesServer(this);
44+ new PropertiesAdaptor(props);
45+ new AccountsUserAdaptor(props);
41− return QDBusConnection::sessionBus().registerObject(path, m_propServer);
46+ return QDBusConnection::sessionBus().registerObject(path, props);
42}
47}
43
48
44bool AccountsServer::RemoveUser(const QString &user)
49bool AccountsServer::RemoveUser(const QString &user)
45{
50{
46 QString path(QString("/%1").arg(user));
51 QString path(QString("/%1").arg(user));
47− if (QDBusConnection::sessionBus().objectRegisteredAt(path) != m_propServer)
52+ if (QDBusConnection::sessionBus().objectRegisteredAt(path) == nullptr)
48 return false;
53 return false;
54+
49 QDBusConnection::sessionBus().unregisterObject(path);
55 QDBusConnection::sessionBus().unregisterObject(path);
50 return true;
56 return true;
51}
57}
tests/plugins/AccountsService/AccountsServer.h+1−6
@@ -25,14 +25,12 @@
25#include <QObject>
25#include <QObject>
26#include <QString>
26#include <QString>
27
27
28−class PropertiesServer;
29−
30class AccountsServer: public QObject, protected QDBusContext
28class AccountsServer: public QObject, protected QDBusContext
31{
29{
32 Q_OBJECT
30 Q_OBJECT
33
31
34public:
32public:
35− explicit AccountsServer(PropertiesServer *propServer, QObject *parent = 0);
33+ explicit AccountsServer(QObject *parent = 0);
36
34
37public Q_SLOTS:
35public Q_SLOTS:
38
36
@@ -41,9 +39,6 @@ public Q_SLOTS:
41 // mock only.
39 // mock only.
42 bool AddUser(const QString &user);
40 bool AddUser(const QString &user);
43 bool RemoveUser(const QString &user);
41 bool RemoveUser(const QString &user);
44−
45−private:
46− PropertiesServer* m_propServer;
47};
42};
48
43
49#endif
44#endif
tests/plugins/AccountsService/PropertiesServer.cpp+9
@@ -23,10 +23,12 @@
23// Qt
23// Qt
24#include <QDebug>
24#include <QDebug>
25#include <QDBusMessage>
25#include <QDBusMessage>
26+#include <QDBusMetaType>
26
27
27PropertiesServer::PropertiesServer(QObject *parent)
28PropertiesServer::PropertiesServer(QObject *parent)
28 : QObject(parent)
29 : QObject(parent)
29{
30{
31+ qDBusRegisterMetaType<QList<QVariantMap>>();
30 Reset();
32 Reset();
31}
33}
32
34
@@ -47,6 +49,12 @@ void PropertiesServer::Set(const QString &interface, const QString &property, co
47 if (m_properties[interface].contains(property)) {
49 if (m_properties[interface].contains(property)) {
48 QVariant& oldValue = m_properties[interface][property];
50 QVariant& oldValue = m_properties[interface][property];
49 if (oldValue != newValue) {
51 if (oldValue != newValue) {
52+ // complex types have an extra layer of wrapping via QDBusArgument
53+ if (interface == QStringLiteral("com.canonical.unity.AccountsService") &&
54+ property == QStringLiteral("LauncherItems")) {
55+ newValue = QVariant::fromValue(qdbus_cast<QList<QVariantMap>>(newValue.value<QDBusArgument>()));
56+ }
57+
50 oldValue = newValue;
58 oldValue = newValue;
51
59
52 // Special case for Background file.
60 // Special case for Background file.
@@ -71,6 +79,7 @@ void PropertiesServer::Set(const QString &interface, const QString &property, co
71void PropertiesServer::Reset()
79void PropertiesServer::Reset()
72{
80{
73 m_properties["com.canonical.unity.AccountsService"]["demo-edges"] = false;
81 m_properties["com.canonical.unity.AccountsService"]["demo-edges"] = false;
82+ m_properties["com.canonical.unity.AccountsService"]["LauncherItems"] = QVariant::fromValue(QList<QVariantMap>());
74 m_properties["com.canonical.unity.AccountsService.Private"]["FailedLogins"] = 0;
83 m_properties["com.canonical.unity.AccountsService.Private"]["FailedLogins"] = 0;
75 m_properties["com.ubuntu.touch.AccountsService.SecurityPrivacy"]["StatsWelcomeScreen"] = true;
84 m_properties["com.ubuntu.touch.AccountsService.SecurityPrivacy"]["StatsWelcomeScreen"] = true;
76 m_properties["com.ubuntu.AccountsService.SecurityPrivacy"]["EnableLauncherWhileLocked"] = true;
85 m_properties["com.ubuntu.AccountsService.SecurityPrivacy"]["EnableLauncherWhileLocked"] = true;
tests/plugins/AccountsService/client.cpp+6−8
@@ -57,8 +57,6 @@ private Q_SLOTS:
57 m_userInterface = new QDBusInterface("org.freedesktop.Accounts",
57 m_userInterface = new QDBusInterface("org.freedesktop.Accounts",
58 QString("/%1").arg(QTest::currentTestFunction()),
58 QString("/%1").arg(QTest::currentTestFunction()),
59 "org.freedesktop.DBus.Properties", QDBusConnection::sessionBus(), this);
59 "org.freedesktop.DBus.Properties", QDBusConnection::sessionBus(), this);
60− QDBusReply<void> resetReply = m_userInterface->call("Reset");
61− QVERIFY(resetReply.isValid());
62
60
63 QVERIFY(QObject::connect(m_userInterface, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)),
61 QVERIFY(QObject::connect(m_userInterface, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)),
64 this, SIGNAL(propertiesChanged(QString, QVariantMap, QStringList))));
62 this, SIGNAL(propertiesChanged(QString, QVariantMap, QStringList))));
@@ -79,17 +77,17 @@ private Q_SLOTS:
79 {
77 {
80 // Test various invalid calls
78 // Test various invalid calls
81 AccountsServiceDBusAdaptor session;
79 AccountsServiceDBusAdaptor session;
82− QCOMPARE(session.getUserProperty("NOPE", "com.canonical.unity.AccountsService", "demo-edges"), QVariant());
80+ QCOMPARE(session.getUserPropertyAsync("NOPE", "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant());
83− QCOMPARE(session.getUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "NOPE"), QVariant());
81+ QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "NOPE").value(), QVariant());
84 }
82 }
85
83
86 void testGetSetServiceDBusAdaptor()
84 void testGetSetServiceDBusAdaptor()
87 {
85 {
88 AccountsServiceDBusAdaptor session;
86 AccountsServiceDBusAdaptor session;
89− session.setUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(true));
87+ session.setUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(true)).waitForFinished();
90− QCOMPARE(session.getUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges"), QVariant(true));
88+ QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant(true));
91− session.setUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(false));
89+ session.setUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(false)).waitForFinished();
92− QCOMPARE(session.getUserProperty(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges"), QVariant(false));
90+ QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant(false));
93 }
91 }
94
92
95 void testGetSetService()
93 void testGetSetService()
tests/plugins/AccountsService/server.cpp+1−7
@@ -19,11 +19,9 @@
19
19
20#include "AccountsAdaptor.h"
20#include "AccountsAdaptor.h"
21#include "AccountsServer.h"
21#include "AccountsServer.h"
22−#include "PropertiesAdaptor.h"
23#include "PropertiesServer.h"
22#include "PropertiesServer.h"
24#include "SecurityPrivacyAdaptor.h"
23#include "SecurityPrivacyAdaptor.h"
25#include "LocationAdaptor.h"
24#include "LocationAdaptor.h"
26−#include "AccountsUserAdaptor.h"
27#include "AccountsPrivateAdaptor.h"
25#include "AccountsPrivateAdaptor.h"
28#include <QCoreApplication>
26#include <QCoreApplication>
29
27
@@ -31,11 +29,7 @@ int main(int argc, char *argv[])
31{
29{
32 QCoreApplication a(argc, argv);
30 QCoreApplication a(argc, argv);
33
31
34− auto props = new PropertiesServer(&a);
35− new PropertiesAdaptor(props);
36− new AccountsUserAdaptor(props);
37−
38− auto accounts = new AccountsServer(props, &a);
32+ auto accounts = new AccountsServer(&a);
39 new AccountsAdaptor(accounts);
33 new AccountsAdaptor(accounts);
40 new SecurityPrivacyAdaptor(accounts);
34 new SecurityPrivacyAdaptor(accounts);
41 new LocationAdaptor(accounts);
35 new LocationAdaptor(accounts);
tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.cppdeleted−48
@@ -1,48 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 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− */
16−
17−#include "AccountsServiceDBusAdaptor.h"
18−#include <QDebug>
19−#include <QDBusArgument>
20−#include <QDBusMessage>
21−#include <QDBusMetaType>
22−
23−AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
24− : QObject(parent)
25−{
26− qDBusRegisterMetaType<QList<QVariantMap>>();
27−}
28−
29−QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
30−{
31− Q_UNUSED(interface)
32− Q_UNUSED(property) // We only fake one property here (LauncherItems)
33−
34− QDBusMessage msg;
35− QVariant v = QVariant::fromValue(mockProperties.value(user));
36− QDBusVariant dv(v);
37− QVariant packed = QVariant::fromValue(dv);
38− msg << packed;
39−
40− return packed.value<QDBusArgument>().asVariant();
41−}
42−
43−void AccountsServiceDBusAdaptor::simulatePropertyChange(const QString &user, const QString &property, const QVariant &value)
44−{
45− Q_ASSERT(property == "LauncherItems");
46− mockProperties[user] = value.value<QList<QVariantMap>>();
47− Q_EMIT propertiesChanged(user, "com.canonical.unity.AccountsService", QStringList() << property);
48−}
tests/plugins/Greeter/Unity/Launcher/AccountsServiceDBusAdaptor.hdeleted−53
@@ -1,53 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 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− */
16−
17−#ifndef UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
18−#define UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
19−
20−#include <QMap>
21−#include <QObject>
22−#include <QString>
23−#include <QHash>
24−#include <QDBusArgument>
25−
26−extern QHash<QString, QList<QVariantMap>> mockProperties;
27−
28−class AccountsServiceDBusAdaptor: public QObject
29−{
30− Q_OBJECT
31−
32−public:
33− explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
34−
35− Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
36− template <typename T>
37− inline T getUserProperty(const QString &user, const QString &interface, const QString &property) {
38− Q_UNUSED(interface)
39− Q_ASSERT(property == "LauncherItems");
40− T ret = mockProperties[user];
41− return ret;
42− }
43−
44−Q_SIGNALS:
45− void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
46−
47−private:
48− void simulatePropertyChange(const QString &user, const QString &property, const QVariant &value);
49−
50− friend class LauncherModelASTest;
51−};
52−
53−#endif
tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+8−2
@@ -3,6 +3,7 @@ pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
3include_directories(
3include_directories(
4 ${CMAKE_CURRENT_SOURCE_DIR}
4 ${CMAKE_CURRENT_SOURCE_DIR}
5 ${CMAKE_CURRENT_BINARY_DIR}
5 ${CMAKE_CURRENT_BINARY_DIR}
6+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
6 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher
7 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher
7 ${libunity8-private_SOURCE_DIR}
8 ${libunity8-private_SOURCE_DIR}
8 )
9 )
@@ -14,7 +15,7 @@ add_definitions(-DLAUNCHER_TESTING)
14### LauncherModelASTest
15### LauncherModelASTest
15add_executable(launchermodelastestExec
16add_executable(launchermodelastestExec
16 launchermodelastest.cpp
17 launchermodelastest.cpp
17− AccountsServiceDBusAdaptor.cpp
18+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
18 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/launchermodelas.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/launchermodelas.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/launcheritem.cpp
20 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/launcheritem.cpp
20 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/quicklistmodel.cpp
21 ${CMAKE_SOURCE_DIR}/plugins/Greeter/Unity/Launcher/quicklistmodel.cpp
@@ -29,10 +30,15 @@ target_link_libraries(launchermodelastestExec
29 unity8-private
30 unity8-private
30 ${GSETTINGS_QT_LDFLAGS}
31 ${GSETTINGS_QT_LDFLAGS}
31 )
32 )
33+add_dependencies(launchermodelastestExec mock-server)
32qt5_use_modules(launchermodelastestExec Test Core DBus Gui)
34qt5_use_modules(launchermodelastestExec Test Core DBus Gui)
33add_unity8_unittest(LauncherModelAS dbus-test-runner
35add_unity8_unittest(LauncherModelAS dbus-test-runner
34 ARG_PREFIX "--parameter"
36 ARG_PREFIX "--parameter"
37+ ARGS
38+ --task $<TARGET_FILE:mock-server>
39+ --ignore-return
35− ARGS --task $<TARGET_FILE:launchermodelastestExec>
40+ --task $<TARGET_FILE:launchermodelastestExec>
41+ --wait-for org.freedesktop.Accounts
36)
42)
37
43
38# copy .desktop files into build directory for shadow builds
44# copy .desktop files into build directory for shadow builds
tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+81−16
@@ -22,9 +22,12 @@
22#include "launchermodelas.h"
22#include "launchermodelas.h"
23#include "AccountsServiceDBusAdaptor.h"
23#include "AccountsServiceDBusAdaptor.h"
24
24
25+#include <QDBusInterface>
26+#include <QDBusMetaType>
27+#include <QDBusReply>
28+#include <QSignalSpy>
25#include <QtTest>
29#include <QtTest>
26
30
27−QHash<QString, QList<QVariantMap>> mockProperties;
28
31
29class LauncherModelASTest : public QObject
32class LauncherModelASTest : public QObject
30{
33{
@@ -32,9 +35,15 @@ class LauncherModelASTest : public QObject
32
35
33private:
36private:
34 LauncherModel *launcherModel;
37 LauncherModel *launcherModel;
38+ QStringList users;
39+ QHash<QString, QList<QVariantMap>> mockProperties;
35
40
36private Q_SLOTS:
41private Q_SLOTS:
37
42
43+ void initTestCase() {
44+ qDBusRegisterMetaType<QList<QVariantMap>>();
45+ }
46+
38 void init() {
47 void init() {
39 // Prepare some fake list
48 // Prepare some fake list
40 QList<QVariantMap> list;
49 QList<QVariantMap> list;
@@ -50,7 +59,63 @@ private Q_SLOTS:
50 item["id"] = "appId2";
59 item["id"] = "appId2";
51 item["name"] = "Item 2";
60 item["name"] = "Item 2";
52 list.append(item);
61 list.append(item);
53− mockProperties["user1"] = list;
62+ setASLauncherItems("user1", list);
63+ }
64+
65+ void cleanup() {
66+ Q_FOREACH(QString user, users) {
67+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
68+ QStringLiteral("/org/freedesktop/Accounts"),
69+ QStringLiteral("org.freedesktop.Accounts"));
70+ QDBusReply<bool> removeReply = accountsInterface.call(QStringLiteral("RemoveUser"),
71+ user);
72+ QVERIFY(removeReply.isValid());
73+ QCOMPARE(removeReply.value(), true);
74+ }
75+
76+ users.clear();
77+ mockProperties.clear();
78+ }
79+
80+ void addASUser(const QString &user)
81+ {
82+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
83+ QStringLiteral("/org/freedesktop/Accounts"),
84+ QStringLiteral("org.freedesktop.Accounts"));
85+ QDBusReply<bool> addReply = accountsInterface.call(QStringLiteral("AddUser"),
86+ user);
87+ QVERIFY(addReply.isValid());
88+ QCOMPARE(addReply.value(), true);
89+
90+ users << user;
91+ mockProperties[user] = QList<QVariantMap>();
92+ }
93+
94+ void setASLauncherItems(const QString &user, const QList<QVariantMap> &items)
95+ {
96+ if (!users.contains(user)) {
97+ addASUser(user);
98+ }
99+
100+ QDBusInterface userInterface(QStringLiteral("org.freedesktop.Accounts"),
101+ QString("/%1").arg(user),
102+ QStringLiteral("org.freedesktop.DBus.Properties"));
103+
104+ QVariant wrapped = QVariant::fromValue(QDBusVariant(QVariant::fromValue(items)));
105+ QDBusReply<void> setReply = userInterface.call(QStringLiteral("Set"),
106+ QStringLiteral("com.canonical.unity.AccountsService"),
107+ QStringLiteral("LauncherItems"),
108+ wrapped);
109+ QVERIFY(setReply.isValid());
110+
111+ // Record what we set for comparison's sake
112+ mockProperties[user] = items;
113+ }
114+
115+ void setUser(LauncherModel *model, const QString &user) {
116+ QSignalSpy spy(model, &QAbstractItemModel::rowsInserted);
117+ model->setUser(user);
118+ QTRY_COMPARE(spy.count(), mockProperties[user].count());
54 }
119 }
55
120
56 bool isInSync(LauncherModel *model, const QList<QVariantMap> &properties) {
121 bool isInSync(LauncherModel *model, const QList<QVariantMap> &properties) {
@@ -81,7 +146,7 @@ private Q_SLOTS:
81 // We didn't set a user yet. model should be empty
146 // We didn't set a user yet. model should be empty
82 QCOMPARE(model->rowCount(), 0);
147 QCOMPARE(model->rowCount(), 0);
83
148
84− model->setUser("user1");
149+ setUser(model, "user1");
85
150
86 QCOMPARE(isInSync(model, mockProperties["user1"]), true);
151 QCOMPARE(isInSync(model, mockProperties["user1"]), true);
87 model->deleteLater();
152 model->deleteLater();
@@ -102,7 +167,7 @@ private Q_SLOTS:
102 QFETCH(bool, inSync);
167 QFETCH(bool, inSync);
103
168
104 LauncherModel* model = new LauncherModel(this);
169 LauncherModel* model = new LauncherModel(this);
105− model->setUser(modelUser);
170+ setUser(model, modelUser);
106
171
107 int oldCount = mockProperties[modelUser].count();
172 int oldCount = mockProperties[modelUser].count();
108 QCOMPARE(model->rowCount(), oldCount);
173 QCOMPARE(model->rowCount(), oldCount);
@@ -117,17 +182,17 @@ private Q_SLOTS:
117 newEntry.insert("countVisible", false);
182 newEntry.insert("countVisible", false);
118 newEntry.insert("pinned", true);
183 newEntry.insert("pinned", true);
119 newList.append(newEntry);
184 newList.append(newEntry);
120− model->m_accounts->simulatePropertyChange(changedUser, "LauncherItems", QVariant::fromValue(newList));
185+ setASLauncherItems(changedUser, newList);
121
186
122− QCOMPARE(isInSync(model, mockProperties[modelUser]), true);
187+ QTRY_COMPARE(isInSync(model, mockProperties[modelUser]), true);
123− QCOMPARE(isInSync(model, mockProperties[changedUser]), inSync);
188+ QTRY_COMPARE(isInSync(model, mockProperties[changedUser]), inSync);
124
189
125 model->deleteLater();
190 model->deleteLater();
126 }
191 }
127
192
128 void testUpdateCount() {
193 void testUpdateCount() {
129 LauncherModel* model = new LauncherModel(this);
194 LauncherModel* model = new LauncherModel(this);
130− model->setUser("user1");
195+ setUser(model, "user1");
131
196
132 QCOMPARE(model->get(0)->countVisible(), false);
197 QCOMPARE(model->get(0)->countVisible(), false);
133 QCOMPARE(model->get(0)->count(), 0);
198 QCOMPARE(model->get(0)->count(), 0);
@@ -137,34 +202,34 @@ private Q_SLOTS:
137 entry["countVisible"] = true;
202 entry["countVisible"] = true;
138 entry["count"] = 55;
203 entry["count"] = 55;
139 newList[0] = entry;
204 newList[0] = entry;
140− model->m_accounts->simulatePropertyChange("user1", "LauncherItems", QVariant::fromValue(newList));
205+ setASLauncherItems("user1", newList);
141
206
142− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
207+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
143
208
144 model->deleteLater();
209 model->deleteLater();
145 }
210 }
146
211
147 void testOnlyPinned() {
212 void testOnlyPinned() {
148 LauncherModel *model = new LauncherModel(this);
213 LauncherModel *model = new LauncherModel(this);
149− model->setUser("user1");
214+ setUser(model, "user1");
150 model->setOnlyPinned(true);
215 model->setOnlyPinned(true);
151
216
152− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
217+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
153
218
154 // Let's unpin one item
219 // Let's unpin one item
155 QList<QVariantMap> newList = mockProperties["user1"];
220 QList<QVariantMap> newList = mockProperties["user1"];
156 QVariantMap entry = newList.at(0);
221 QVariantMap entry = newList.at(0);
157 entry["pinned"] = false;
222 entry["pinned"] = false;
158 newList[0] = entry;
223 newList[0] = entry;
159− model->m_accounts->simulatePropertyChange("user1", "LauncherItems", QVariant::fromValue(newList));
224+ setASLauncherItems("user1", newList);
160− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
225+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
161
226
162 // Now toggle onlyPinned and make sure the model keeps up
227 // Now toggle onlyPinned and make sure the model keeps up
163 model->setOnlyPinned(false);
228 model->setOnlyPinned(false);
164− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
229+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
165
230
166 model->setOnlyPinned(true);
231 model->setOnlyPinned(true);
167− QCOMPARE(isInSync(model, mockProperties["user1"]), true);
232+ QTRY_COMPARE(isInSync(model, mockProperties["user1"]), true);
168 }
233 }
169};
234};
170
235
tests/plugins/Unity/Launcher/AccountsServiceDBusAdaptor.cppdeleted−42
@@ -1,42 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 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− */
16−
17−#include "AccountsServiceDBusAdaptor.h"
18−#include <QDebug>
19−
20−AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
21− : QObject(parent)
22−{
23−}
24−
25−QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
26−{
27− Q_UNUSED(user)
28− Q_UNUSED(interface)
29− return m_properties.value(property);
30−}
31−
32−void AccountsServiceDBusAdaptor::setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value)
33−{
34− Q_UNUSED(user)
35− Q_UNUSED(interface)
36− m_properties[property] = value;
37−}
38−
39−void AccountsServiceDBusAdaptor::setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value)
40−{
41− setUserProperty(user, interface, property, value);
42−}
tests/plugins/Unity/Launcher/AccountsServiceDBusAdaptor.hdeleted−47
@@ -1,47 +0,0 @@
1−/*
2− * Copyright (C) 2014-2015 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− */
16−
17−#ifndef UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
18−#define UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
19−
20−#include <QMap>
21−#include <QObject>
22−#include <QString>
23−#include <QHash>
24−
25−class AccountsServiceDBusAdaptor: public QObject
26−{
27− Q_OBJECT
28−
29−public:
30− explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
31−
32− Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
33− Q_INVOKABLE void setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value);
34− Q_INVOKABLE void setUserPropertyAsync(const QString &user, const QString &interface, const QString &property, const QVariant &value);
35−
36−Q_SIGNALS:
37− void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
38− void maybeChanged(const QString &user); // Standard properties might have changed
39−
40−private:
41− void simulatePropertyChange(const QString &property, const QVariant &value);
42−
43−private:
44− QHash<QString, QVariant> m_properties;
45−};
46−
47−#endif
tests/plugins/Unity/Launcher/CMakeLists.txt+8−2
@@ -4,6 +4,7 @@ pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
4include_directories(
4include_directories(
5 ${CMAKE_CURRENT_SOURCE_DIR}
5 ${CMAKE_CURRENT_SOURCE_DIR}
6 ${CMAKE_CURRENT_BINARY_DIR}
6 ${CMAKE_CURRENT_BINARY_DIR}
7+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
7 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
8 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
8 ${GSETTINGS_QT_INCLUDE_DIRS}
9 ${GSETTINGS_QT_INCLUDE_DIRS}
9 ${libunity8-private_SOURCE_DIR}
10 ${libunity8-private_SOURCE_DIR}
@@ -17,7 +18,7 @@ add_definitions(-DLAUNCHER_TESTING)
17add_executable(launchermodeltestExec
18add_executable(launchermodeltestExec
18 launchermodeltest.cpp
19 launchermodeltest.cpp
19 gsettings.cpp
20 gsettings.cpp
20− AccountsServiceDBusAdaptor.cpp
21+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
21 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launchermodel.cpp
22 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launchermodel.cpp
22 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/asadapter.cpp
23 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/asadapter.cpp
23 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launcheritem.cpp
24 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launcheritem.cpp
@@ -35,11 +36,16 @@ target_link_libraries(launchermodeltestExec
35 unity8-private
36 unity8-private
36 ${GSETTINGS_QT_LDFLAGS}
37 ${GSETTINGS_QT_LDFLAGS}
37 )
38 )
39+add_dependencies(launchermodeltestExec mock-server)
38qt5_use_modules(launchermodeltestExec Test Core DBus Xml Gui)
40qt5_use_modules(launchermodeltestExec Test Core DBus Xml Gui)
39
41
40add_unity8_unittest(LauncherModel dbus-test-runner
42add_unity8_unittest(LauncherModel dbus-test-runner
41 ARG_PREFIX "--parameter"
43 ARG_PREFIX "--parameter"
44+ ARGS
45+ --task $<TARGET_FILE:mock-server>
46+ --ignore-return
42− ARGS --task $<TARGET_FILE:launchermodeltestExec>
47+ --task $<TARGET_FILE:launchermodeltestExec>
48+ --wait-for org.freedesktop.Accounts
43)
49)
44
50
45# copy .desktop files into build directory for shadow builds
51# copy .desktop files into build directory for shadow builds
tests/plugins/Unity/Launcher/launchermodeltest.cpp+23−1
@@ -31,6 +31,7 @@
31#include <QtTest>
31#include <QtTest>
32#include <QDBusInterface>
32#include <QDBusInterface>
33#include <QDBusReply>
33#include <QDBusReply>
34+#include <QDBusMetaType>
34#include <QDomDocument>
35#include <QDomDocument>
35
36
36// This is a mock, specifically to test the LauncherModel
37// This is a mock, specifically to test the LauncherModel
@@ -136,12 +137,17 @@ private:
136
137
137 QList<QVariantMap> getASConfig() {
138 QList<QVariantMap> getASConfig() {
138 AccountsServiceDBusAdaptor *as = launcherModel->m_asAdapter->m_accounts;
139 AccountsServiceDBusAdaptor *as = launcherModel->m_asAdapter->m_accounts;
139− return as->getUserProperty("", "", "LauncherItems").value<QList<QVariantMap>>();
140+ QDBusReply<QVariant> reply = as->getUserPropertyAsync(QString(qgetenv("USER")),
141+ "com.canonical.unity.AccountsService",
142+ "LauncherItems");
143+ return qdbus_cast<QList<QVariantMap>>(reply.value().value<QDBusArgument>());
140 }
144 }
141
145
142private Q_SLOTS:
146private Q_SLOTS:
143
147
144 void initTestCase() {
148 void initTestCase() {
149+ qDBusRegisterMetaType<QList<QVariantMap>>();
150+
145 launcherModel = new LauncherModel(this);
151 launcherModel = new LauncherModel(this);
146 QCoreApplication::processEvents(); // to let the model register on DBus
152 QCoreApplication::processEvents(); // to let the model register on DBus
147 QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
153 QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
@@ -152,6 +158,14 @@ private Q_SLOTS:
152
158
153 // Adding 2 apps to the mock appmanager. Both should appear in the launcher.
159 // Adding 2 apps to the mock appmanager. Both should appear in the launcher.
154 void init() {
160 void init() {
161+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
162+ QStringLiteral("/org/freedesktop/Accounts"),
163+ QStringLiteral("org.freedesktop.Accounts"));
164+ QDBusReply<bool> addReply = accountsInterface.call(QStringLiteral("AddUser"),
165+ QString(qgetenv("USER")));
166+ QVERIFY(addReply.isValid());
167+ QCOMPARE(addReply.value(), true);
168+
155 appManager->addApplication(new MockApp("abs-icon"));
169 appManager->addApplication(new MockApp("abs-icon"));
156 QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
170 QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
157
171
@@ -169,6 +183,14 @@ private Q_SLOTS:
169 while (launcherModel->rowCount(QModelIndex()) > 0) {
183 while (launcherModel->rowCount(QModelIndex()) > 0) {
170 launcherModel->requestRemove(launcherModel->get(0)->appId());
184 launcherModel->requestRemove(launcherModel->get(0)->appId());
171 }
185 }
186+
187+ QDBusInterface accountsInterface(QStringLiteral("org.freedesktop.Accounts"),
188+ QStringLiteral("/org/freedesktop/Accounts"),
189+ QStringLiteral("org.freedesktop.Accounts"));
190+ QDBusReply<bool> removeReply = accountsInterface.call(QStringLiteral("RemoveUser"),
191+ QString(qgetenv("USER")));
192+ QVERIFY(removeReply.isValid());
193+ QCOMPARE(removeReply.value(), true);
172 }
194 }
173
195
174 void testMove() {
196 void testMove() {