refact: change dbus api and service impl
1. change IconName and DisplayName to method 2. refactor impl of GetManagedObject and move it to global.h 3. refactor impl of JobService::status 4. add ut_job.cpp Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
parent
d49a99d252
commit
0e7d84f61d
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
<property name="AutoStart" type="b" access="readwrite"/>
|
<property name="AutoStart" type="b" access="readwrite"/>
|
||||||
|
|
||||||
<property name="IconName" type="s" access="read"/>
|
|
||||||
|
|
||||||
<property name="DisplayName" type="s" access="read"/>
|
|
||||||
|
|
||||||
<property name="Instances" type="ao" access="read">
|
<property name="Instances" type="ao" access="read">
|
||||||
<annotation
|
<annotation
|
||||||
name="org.freedesktop.DBus.Description"
|
name="org.freedesktop.DBus.Description"
|
||||||
@ -102,5 +98,23 @@
|
|||||||
this method will use the locale config of that user."
|
this method will use the locale config of that user."
|
||||||
/>
|
/>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<method name="GetIconName">
|
||||||
|
<arg name="action" type="s" direction="in"/>
|
||||||
|
<arg name="name" type="s" direction="out"/>
|
||||||
|
<annotation
|
||||||
|
name="org.freedesktop.DBus.Description"
|
||||||
|
value="The meaning of arg `env` is same as which in GetActionName."
|
||||||
|
/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="GetDisplayName">
|
||||||
|
<arg name="env" type="as" direction="in"/>
|
||||||
|
<arg name="name" type="s" direction="out"/>
|
||||||
|
<annotation
|
||||||
|
name="org.freedesktop.DBus.Description"
|
||||||
|
value="The meaning of arg `env` is same as which in GetActionName."
|
||||||
|
/>
|
||||||
|
</method>
|
||||||
</interface>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
|
@ -218,12 +218,5 @@ void ApplicationManager1Service::UpdateApplicationInfo(const QStringList &appIdL
|
|||||||
|
|
||||||
ObjectMap ApplicationManager1Service::GetManagedObjects() const
|
ObjectMap ApplicationManager1Service::GetManagedObjects() const
|
||||||
{
|
{
|
||||||
ObjectMap objs;
|
return dumpDBusObject(m_applicationList);
|
||||||
|
|
||||||
for (const auto &[key, value] : m_applicationList.asKeyValueRange()) {
|
|
||||||
auto interfaces = getInterfacesListFromObject(value.data());
|
|
||||||
objs.insert(key, interfaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
return objs;
|
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QSharedPointer<ApplicationService> makeApplication(T &&source, ApplicationManager1Service *parent)
|
QSharedPointer<ApplicationService> makeApplication(T &&source,
|
||||||
|
ApplicationManager1Service *parent) // NOTE: maybe we should refactor
|
||||||
{
|
{
|
||||||
static_assert(std::is_same_v<T, DesktopFile> or std::is_same_v<T, QString>, "param type must be QString or DesktopFile.");
|
static_assert(std::is_same_v<T, DesktopFile> or std::is_same_v<T, QString>, "param type must be QString or DesktopFile.");
|
||||||
QString objectPath;
|
QString objectPath;
|
||||||
|
@ -25,7 +25,7 @@ ApplicationService::~ApplicationService()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ApplicationService::GetActionName(const QString &identifier, const QStringList &env)
|
QString ApplicationService::GetActionName(const QString &identifier, const QStringList &env) const
|
||||||
{
|
{
|
||||||
const auto &supportedActions = actions();
|
const auto &supportedActions = actions();
|
||||||
if (supportedActions.isEmpty()) {
|
if (supportedActions.isEmpty()) {
|
||||||
@ -68,6 +68,67 @@ QString ApplicationService::GetActionName(const QString &identifier, const QStri
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ApplicationService::GetDisplayName(const QStringList &env) const
|
||||||
|
{
|
||||||
|
const auto &displayName = m_entry->value(DesktopFileEntryKey, "Name");
|
||||||
|
if (!displayName) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString locale{""};
|
||||||
|
bool ok;
|
||||||
|
if (!env.isEmpty()) {
|
||||||
|
QString lcStr;
|
||||||
|
for (const auto &lc : env) {
|
||||||
|
if (lc.startsWith("LANG")) {
|
||||||
|
locale = lc.split('=').last();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lc.startsWith("LC_ALL")) {
|
||||||
|
locale = lc.split('=').last();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QLocale lc = locale.isEmpty() ? getUserLocale() : QLocale{locale};
|
||||||
|
|
||||||
|
const auto &name = displayName->toLocaleString(lc, ok);
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "convert to locale string failed, dest locale:" << lc;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ApplicationService::GetIconName(const QString &action) const
|
||||||
|
{
|
||||||
|
std::optional<DesktopEntry::Value> iconName{std::nullopt};
|
||||||
|
|
||||||
|
if (action.isEmpty()) {
|
||||||
|
iconName = m_entry->value(DesktopFileEntryKey, "Icon");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const auto &supportedActions = actions();
|
||||||
|
|
||||||
|
if (auto index = supportedActions.indexOf(action); index == -1) {
|
||||||
|
qWarning() << "can't find " << action << " in supported actions List.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &actionHeader = QString{"%1%2"}.arg(DesktopFileActionKey, action);
|
||||||
|
iconName = m_entry->value(actionHeader, "Icon");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iconName) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok{false};
|
||||||
|
const auto &name = iconName->toIconString(ok);
|
||||||
|
return ok ? name : "";
|
||||||
|
}
|
||||||
|
|
||||||
QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, QVariantMap options)
|
QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, QVariantMap options)
|
||||||
{
|
{
|
||||||
QString execStr;
|
QString execStr;
|
||||||
@ -208,14 +269,7 @@ QStringList ApplicationService::actions() const noexcept
|
|||||||
|
|
||||||
ObjectMap ApplicationService::GetManagedObjects() const
|
ObjectMap ApplicationService::GetManagedObjects() const
|
||||||
{
|
{
|
||||||
ObjectMap objs;
|
return dumpDBusObject(m_Instances);
|
||||||
|
|
||||||
for (const auto &[key, value] : m_Instances.asKeyValueRange()) {
|
|
||||||
auto interfaces = getInterfacesListFromObject(value.data());
|
|
||||||
objs.insert(key, interfaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
return objs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ApplicationService::id() const noexcept
|
QString ApplicationService::id() const noexcept
|
||||||
@ -254,50 +308,6 @@ QList<QDBusObjectPath> ApplicationService::instances() const noexcept
|
|||||||
return m_Instances.keys();
|
return m_Instances.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ApplicationService::iconName() const noexcept
|
|
||||||
{
|
|
||||||
if (m_entry.isNull()) {
|
|
||||||
qWarning() << "desktop entry is empty, isPersistence:" << m_isPersistence;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &actions = m_entry->value(DesktopFileEntryKey, "Icon");
|
|
||||||
if (!actions) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok{false};
|
|
||||||
const auto &icon = actions->toIconString(ok);
|
|
||||||
if (!ok) {
|
|
||||||
qWarning() << "Icon convert to String failed.";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ApplicationService::displayName() const noexcept
|
|
||||||
{
|
|
||||||
if (m_entry.isNull()) {
|
|
||||||
qWarning() << "desktop entry is empty, isPersistence:" << m_isPersistence;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &actions = m_entry->value(DesktopFileEntryKey, "Name");
|
|
||||||
if (!actions) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok{false};
|
|
||||||
const auto &name = actions->toString(ok);
|
|
||||||
if (!ok) {
|
|
||||||
qWarning() << "Icon convert to String failed.";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ApplicationService::addOneInstance(const QString &instanceId, const QString &application, const QString &systemdUnitPath)
|
bool ApplicationService::addOneInstance(const QString &instanceId, const QString &application, const QString &systemdUnitPath)
|
||||||
{
|
{
|
||||||
auto service = new InstanceService{instanceId, application, systemdUnitPath};
|
auto service = new InstanceService{instanceId, application, systemdUnitPath};
|
||||||
|
@ -48,12 +48,6 @@ public:
|
|||||||
Q_PROPERTY(QList<QDBusObjectPath> Instances READ instances)
|
Q_PROPERTY(QList<QDBusObjectPath> Instances READ instances)
|
||||||
[[nodiscard]] QList<QDBusObjectPath> instances() const noexcept;
|
[[nodiscard]] QList<QDBusObjectPath> instances() const noexcept;
|
||||||
|
|
||||||
Q_PROPERTY(QString IconName READ iconName CONSTANT)
|
|
||||||
[[nodiscard]] QString iconName() const noexcept;
|
|
||||||
|
|
||||||
Q_PROPERTY(QString DisplayName READ displayName CONSTANT)
|
|
||||||
[[nodiscard]] QString displayName() const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] QDBusObjectPath findInstance(const QString &instanceId) const;
|
[[nodiscard]] QDBusObjectPath findInstance(const QString &instanceId) const;
|
||||||
|
|
||||||
[[nodiscard]] const QString &getLauncher() const noexcept { return m_launcher; }
|
[[nodiscard]] const QString &getLauncher() const noexcept { return m_launcher; }
|
||||||
@ -65,8 +59,10 @@ public:
|
|||||||
void removeAllInstance();
|
void removeAllInstance();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
QString GetActionName(const QString &identifier, const QStringList &env);
|
[[nodiscard]] QString GetActionName(const QString &identifier, const QStringList &env) const;
|
||||||
QDBusObjectPath Launch(QString action, QStringList fields, QVariantMap options);
|
QDBusObjectPath Launch(QString action, QStringList fields, QVariantMap options);
|
||||||
|
[[nodiscard]] QString GetIconName(const QString &action) const;
|
||||||
|
[[nodiscard]] QString GetDisplayName(const QStringList &env) const;
|
||||||
[[nodiscard]] ObjectMap GetManagedObjects() const;
|
[[nodiscard]] ObjectMap GetManagedObjects() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
@ -11,27 +11,29 @@ JobService::JobService(const QFuture<QVariantList> &job)
|
|||||||
|
|
||||||
JobService::~JobService() = default;
|
JobService::~JobService() = default;
|
||||||
|
|
||||||
QString JobService::status() const // FIXME: job status aren't mutually exclusive
|
QString JobService::status() const
|
||||||
{
|
{
|
||||||
if (m_job.isFinished()) {
|
if (m_job.isStarted()) {
|
||||||
return "finished";
|
if (m_job.isRunning()) {
|
||||||
}
|
if (m_job.isSuspending()) {
|
||||||
if (m_job.isCanceled()) {
|
return "suspending";
|
||||||
return "canceled";
|
|
||||||
}
|
}
|
||||||
if (m_job.isSuspended()) {
|
if (m_job.isSuspended()) {
|
||||||
return "suspended";
|
return "suspended";
|
||||||
}
|
}
|
||||||
if (m_job.isSuspending()) {
|
|
||||||
return "suspending";
|
|
||||||
}
|
|
||||||
if (m_job.isStarted()) {
|
|
||||||
return "started";
|
|
||||||
}
|
|
||||||
if (m_job.isRunning()) {
|
|
||||||
return "running";
|
return "running";
|
||||||
}
|
}
|
||||||
Q_UNREACHABLE();
|
|
||||||
|
if (m_job.isCanceled()) {
|
||||||
|
return "canceled";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_job.isFinished()) {
|
||||||
|
return "finished";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "pending";
|
||||||
}
|
}
|
||||||
|
|
||||||
void JobService::Cancel()
|
void JobService::Cancel()
|
||||||
|
13
src/global.h
13
src/global.h
@ -361,4 +361,17 @@ inline QPair<QString, QString> processUnitName(const QString &unitName)
|
|||||||
return qMakePair(unescapeApplicationId(applicationId), std::move(instanceId));
|
return qMakePair(unescapeApplicationId(applicationId), std::move(instanceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
ObjectMap dumpDBusObject(const QMap<QDBusObjectPath, QSharedPointer<T>> &map)
|
||||||
|
{
|
||||||
|
ObjectMap objs;
|
||||||
|
|
||||||
|
for (const auto &[key, value] : map.asKeyValueRange()) {
|
||||||
|
auto interfaces = getInterfacesListFromObject(value.data());
|
||||||
|
objs.insert(key, interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
return objs;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
104
tests/ut_job.cpp
Normal file
104
tests/ut_job.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "dbus/jobservice.h"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <QFuture>
|
||||||
|
#include <QPromise>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <QSemaphore>
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
class TestJob : public testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void SetUp() override
|
||||||
|
{
|
||||||
|
QPromise<QVariantList> promise;
|
||||||
|
m_jobService = new JobService{promise.future()};
|
||||||
|
|
||||||
|
m_thread = QThread::create(
|
||||||
|
[](QPromise<QVariantList> promise) {
|
||||||
|
std::this_thread::sleep_for(2ms);
|
||||||
|
promise.start();
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
if (promise.isCanceled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
promise.suspendIfRequested();
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
|
||||||
|
std::size_t x{0};
|
||||||
|
for (std::size_t i = 0; i < 20000; ++i) {
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.addResult(QVariantList{QVariant::fromValue<std::size_t>(x)});
|
||||||
|
promise.finish();
|
||||||
|
},
|
||||||
|
std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override
|
||||||
|
{
|
||||||
|
m_thread->quit();
|
||||||
|
m_thread->deleteLater();
|
||||||
|
m_thread = nullptr;
|
||||||
|
|
||||||
|
m_jobService->deleteLater();
|
||||||
|
m_jobService = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QThread *m_thread{nullptr};
|
||||||
|
JobService *m_jobService{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(TestJob, cancelJob)
|
||||||
|
{
|
||||||
|
m_thread->start();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"pending"});
|
||||||
|
std::this_thread::sleep_for(2ms);
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"running"});
|
||||||
|
|
||||||
|
m_jobService->Cancel();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"canceled"});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestJob, suspendAndResumeJob)
|
||||||
|
{
|
||||||
|
m_thread->start();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(3ms);
|
||||||
|
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"running"});
|
||||||
|
|
||||||
|
m_jobService->Suspend();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"suspending"});
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"suspended"});
|
||||||
|
m_jobService->Resume();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"running"});
|
||||||
|
|
||||||
|
EXPECT_TRUE(m_thread->wait());
|
||||||
|
EXPECT_EQ(m_jobService->status().toStdString(), std::string{"finished"});
|
||||||
|
|
||||||
|
auto ret = m_jobService->m_job.result();
|
||||||
|
EXPECT_FALSE(ret.isEmpty());
|
||||||
|
|
||||||
|
EXPECT_EQ(ret.first().value<std::size_t>(), std::size_t{20000});
|
||||||
|
}
|
@ -10,7 +10,7 @@ class TestJobManager : public testing::Test
|
|||||||
public:
|
public:
|
||||||
static void SetUpTestCase() { m_jobManager = new JobManager1Service(nullptr); }
|
static void SetUpTestCase() { m_jobManager = new JobManager1Service(nullptr); }
|
||||||
|
|
||||||
static void TearDownTestCase() { delete m_jobManager; }
|
static void TearDownTestCase() { m_jobManager->deleteLater(); }
|
||||||
JobManager1Service &service() { return *m_jobManager; }
|
JobManager1Service &service() { return *m_jobManager; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user