/* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * version 3 along with this program. If not, see * * * Authored by: Michael Terry */ #include "AccountsService.h" #include "AccountsServiceDBusAdaptor.h" #include "types.h" #include #include #include #include #include template QVariant dbusVariant(const T& value) { return QVariant::fromValue(QDBusVariant(value)); } #define ASSERT_DBUS_CALL(call) \ { \ QDBusReply reply = call; \ if (!reply.isValid()) QFAIL(reply.error().message().toLatin1()); \ } class AccountsServiceTest : public QObject { Q_OBJECT public: AccountsServiceTest(QObject* parent = 0) : QObject(parent) , m_userInterface(nullptr) , m_spy(this, &AccountsServiceTest::propertiesChanged) , m_mousePrimaryButtonSpy(this, &AccountsServiceTest::setMousePrimaryButtonCalled) { m_uscInputInterface = new QDBusInterface("com.canonical.Unity.Input", "/com/canonical/Unity/Input", "com.canonical.Unity.Input", QDBusConnection::sessionBus(), this); QObject::connect(m_uscInputInterface, SIGNAL(setMousePrimaryButtonCalled(int)), this, SIGNAL(setMousePrimaryButtonCalled(int))); qDBusRegisterMetaType(); qDBusRegisterMetaType(); } private Q_SLOTS: void init() { QDBusReply addReply = QDBusInterface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts").call("AddUser", QTest::currentTestFunction()); QVERIFY(addReply.isValid()); QCOMPARE(addReply.value(), true); m_userInterface = new QDBusInterface("org.freedesktop.Accounts", QString("/%1").arg(QTest::currentTestFunction()), "org.freedesktop.DBus.Properties", QDBusConnection::sessionBus(), this); QVERIFY(QObject::connect(m_userInterface, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)), this, SIGNAL(propertiesChanged(QString, QVariantMap, QStringList)))); } void cleanup() { QDBusReply reply = QDBusInterface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts").call("RemoveUser", QTest::currentTestFunction()); QVERIFY(reply.isValid()); QCOMPARE(reply.value(), true); delete m_userInterface; m_spy.clear(); m_mousePrimaryButtonSpy.clear(); } void testInvalids() { // Test various invalid calls AccountsServiceDBusAdaptor session; QCOMPARE(session.getUserPropertyAsync("NOPE", "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant()); QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "NOPE").value(), QVariant()); } void testGetSetServiceDBusAdaptor() { AccountsServiceDBusAdaptor session; session.setUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(true)).waitForFinished(); QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant(true)); session.setUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges", QVariant(false)).waitForFinished(); QCOMPARE(session.getUserPropertyAsync(QTest::currentTestFunction(), "com.canonical.unity.AccountsService", "demo-edges").value(), QVariant(false)); } void testGetSetService() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.demoEdges(), false); session.setDemoEdges(true); QCOMPARE(session.demoEdges(), true); QCOMPARE(session.failedLogins(), (uint)0); session.setFailedLogins(5); QCOMPARE(session.failedLogins(), (uint)5); QCOMPARE(session.hereEnabled(), false); session.setHereEnabled(true); QCOMPARE(session.hereEnabled(), true); } void testMarkDemoEdgeCompleted() { AccountsService session(this, QTest::currentTestFunction()); QSignalSpy changedSpy(&session, &AccountsService::demoEdgesCompletedChanged); QCOMPARE(changedSpy.count(), 0); QCOMPARE(session.demoEdgesCompleted(), QStringList()); session.markDemoEdgeCompleted("testedge"); QCOMPARE(changedSpy.count(), 1); QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge"); session.markDemoEdgeCompleted("testedge"); QCOMPARE(changedSpy.count(), 1); QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge"); session.markDemoEdgeCompleted("testedge2"); QCOMPARE(changedSpy.count(), 2); QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge" << "testedge2"); } void testAsynchronousChangeForDemoEdgesCompleted() { AccountsService session(this, QTest::currentTestFunction()); QSignalSpy changedSpy(&session, &AccountsService::demoEdgesCompletedChanged); QCOMPARE(changedSpy.count(), 0); QCOMPARE(session.demoEdgesCompleted(), QStringList()); ASSERT_DBUS_CALL(m_userInterface->call("Set", "com.canonical.unity.AccountsService", "DemoEdgesCompleted", dbusVariant(QStringList() << "testedge"))); QTRY_COMPARE(changedSpy.count(), 1); QCOMPARE(session.demoEdgesCompleted(), QStringList() << "testedge"); } void testAsynchronousChangeForDemoEdges() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.demoEdges(), false); ASSERT_DBUS_CALL(m_userInterface->call("Set", "com.canonical.unity.AccountsService", "demo-edges", dbusVariant(true))); QTRY_COMPARE(session.demoEdges(), true); } void testAsynchronousChangeForFailedLogins() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.failedLogins(), (uint)0); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.canonical.unity.AccountsService.Private", "FailedLogins", dbusVariant(5))); QTRY_COMPARE(session.failedLogins(), (uint)5); } void testAsynchronousChangeForStatsWelcomeScreen() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.statsWelcomeScreen(), true); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.touch.AccountsService.SecurityPrivacy", "StatsWelcomeScreen", dbusVariant(false))); QTRY_COMPARE(session.statsWelcomeScreen(), false); } void testAsynchronousChangeForEnableLauncherWhileLocked() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.enableLauncherWhileLocked(), true); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.AccountsService.SecurityPrivacy", "EnableLauncherWhileLocked", dbusVariant(false))); QTRY_COMPARE(session.enableLauncherWhileLocked(), false); } void testAsynchronousChangeForEnableIndicatorsWhileLocked() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.enableIndicatorsWhileLocked(), true); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.AccountsService.SecurityPrivacy", "EnableIndicatorsWhileLocked", dbusVariant(false))); QTRY_COMPARE(session.enableIndicatorsWhileLocked(), false); } void testAsynchronousChangeForPasswordDisplayHint() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.passwordDisplayHint(), AccountsService::Keyboard); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.AccountsService.SecurityPrivacy", "PasswordDisplayHint", dbusVariant(AccountsService::Numeric))); QTRY_COMPARE(session.passwordDisplayHint(), AccountsService::Numeric); } void testAsynchronousChangeForLicenseAccepted() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.hereEnabled(), false); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.location.providers.here.AccountsService", "LicenseAccepted", dbusVariant(true))); QTRY_COMPARE(session.hereEnabled(), true); } void testAsynchronousChangeForLicenseBasePath() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.hereLicensePath(), QString()); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.location.providers.here.AccountsService", "LicenseBasePath", dbusVariant("/"))); QTRY_COMPARE(session.hereLicensePath(), QString("/")); } void testAsynchronousChangeForBackgroundFile() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.backgroundFile(), QString()); QDBusInterface accountsIface(m_userInterface->service(), m_userInterface->path(), "org.freedesktop.Accounts.User"); ASSERT_DBUS_CALL(accountsIface.asyncCall("SetBackgroundFile", "/test/BackgroundFile")); QTRY_COMPARE(session.backgroundFile(), QString("/test/BackgroundFile")); } void testProxyOnStartup() { AccountsService session(this, QTest::currentTestFunction()); QTRY_COMPARE(m_mousePrimaryButtonSpy.count(), 1); QList arguments = m_mousePrimaryButtonSpy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 1); } void testProxyOnChange() { AccountsService session(this, QTest::currentTestFunction()); QTRY_COMPARE(m_mousePrimaryButtonSpy.count(), 1); m_mousePrimaryButtonSpy.clear(); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.AccountsService.Input", "MousePrimaryButton", dbusVariant("left"))); QTRY_COMPARE(m_mousePrimaryButtonSpy.count(), 1); QList arguments = m_mousePrimaryButtonSpy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 0); } void testInvalidPrimaryButton() { AccountsService session(this, QTest::currentTestFunction()); QTRY_COMPARE(m_mousePrimaryButtonSpy.count(), 1); m_mousePrimaryButtonSpy.clear(); ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set", "com.ubuntu.AccountsService.Input", "MousePrimaryButton", dbusVariant("NOPE"))); QTRY_COMPARE(m_mousePrimaryButtonSpy.count(), 1); QList arguments = m_mousePrimaryButtonSpy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 0); } void testSetRealName() { AccountsService session(this, QTest::currentTestFunction()); // Just confirm that we can't set normal way auto message = m_userInterface->call("Set", "org.freedesktop.Accounts.User", "RealName", dbusVariant("Stallman")); QCOMPARE(message.type(), QDBusMessage::ErrorMessage); QCOMPARE(message.errorName(), QStringLiteral("org.freedesktop.DBus.Error.InvalidArgs")); message = m_userInterface->call("Get", "org.freedesktop.Accounts.User", "RealName"); QCOMPARE(message.type(), QDBusMessage::ReplyMessage); auto response = message.arguments().first().value().variant().toString(); QCOMPARE(response, QStringLiteral("")); // Now try it via our AS wrapper and confirm it did get through, unlike above session.setRealName("Stallman"); QCOMPARE(session.realName(), QStringLiteral("Stallman")); message = m_userInterface->call("Get", "org.freedesktop.Accounts.User", "RealName"); QCOMPARE(message.type(), QDBusMessage::ReplyMessage); response = message.arguments().first().value().variant().toString(); QCOMPARE(response, QStringLiteral("Stallman")); } void testAsynchronousChangeForKeymaps() { AccountsService session(this, QTest::currentTestFunction()); QCOMPARE(session.keymaps(), {"us"}); StringMapList inputSources; StringMap map1; map1.insert("xkb", "cz+qwerty"); inputSources.append(map1); StringMap map2; map2.insert("xkb", "fr"); inputSources.append(map2); QDBusInterface accountsIface(m_userInterface->service(), m_userInterface->path(), "org.freedesktop.Accounts.User"); ASSERT_DBUS_CALL(accountsIface.asyncCall("SetInputSources", QVariant::fromValue(inputSources))); QStringList result = {"cz+qwerty", "fr"}; QTRY_COMPARE(session.keymaps(), result); } Q_SIGNALS: void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid); void setMousePrimaryButtonCalled(int button); private: QDBusInterface* m_uscInputInterface; QDBusInterface* m_userInterface; QSignalSpy m_spy; QSignalSpy m_mousePrimaryButtonSpy; }; QTEST_MAIN(AccountsServiceTest) #include "client.moc"