feat: add test for desktopentry and jobmanager

Log:
This commit is contained in:
heyuming
2023-07-19 17:56:45 +08:00
committed by black-desk
parent d288752fb3
commit 5fed3ed9f0
19 changed files with 451 additions and 92 deletions

View File

@ -1,31 +1,26 @@
include(GNUInstallDirs)
set(BIN_NAME dde-application-manager)
set(LIB_NAME ddeam)
set(DBUS_INTERFACE_DIR ${CMAKE_CURRENT_LIST_DIR}/dbus)
file(GLOB_RECURSE SRCS ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
set(DBUSADAPTORS "")
file(GLOB_RECURSE SRCS ${CMAKE_CURRENT_LIST_DIR}/*.cpp ${CMAKE_CURRENT_LIST_DIR}/*.h)
list(REMOVE_ITEM SRCS "${PROJECT_SOURCE_DIR}/src/utils.cpp")
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ApplicationManager1.xml applicationmanager1service.h ApplicationManager1Service)
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ApplicationManager1.Application.xml applicationservice.h ApplicationService)
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ApplicationManager1.Instance.xml instanceservice.h InstanceService)
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.JobManager1.xml jobmanager1service.h JobManager1Service)
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.JobManager1.Job.xml jobservice.h JobService)
add_library(${LIB_NAME} ${SRCS})
add_executable(${BIN_NAME} ${DBUSADAPTORS} ${SRCS})
target_include_directories(${BIN_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_CURRENT_LIST_DIR}/dbus
${CMAKE_CURRENT_BINARY_DIR}/src
target_include_directories(${LIB_NAME} PRIVATE
${PROJECT_BINARY_DIR}
)
target_link_libraries(${BIN_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::DBus
Qt${QT_VERSION_MAJOR}::Concurrent
target_link_libraries(${LIB_NAME} PUBLIC
Threads::Threads
${AdaptorLib}
)
add_executable(${BIN_NAME} main.cpp utils.cpp)
target_link_libraries(${BIN_NAME} PRIVATE
${LIB_NAME}
)
install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "applicationmanager1service.h"
#include "applicationmanager1adaptor.h"
#include "applicationadaptor.h"
#include "global.h"
@ -46,7 +45,7 @@ QDBusObjectPath ApplicationManager1Service::Launch(const QString &id,
objectPath.prepend(DDEApplicationManager1ApplicationObjectPath);
QSharedPointer<ApplicationService> app{new ApplicationService{id}};
auto *ptr = app.data();
if (registerObjectToDbus<decltype(ptr), ApplicationAdaptor>(ptr, objectPath, getDBusInterface<ApplicationAdaptor>())) {
if (registerObjectToDbus(new ApplicationAdaptor(ptr), objectPath, getDBusInterface<ApplicationAdaptor>())) {
QDBusObjectPath path{objectPath};
m_applicationList.insert(path, app);
return path;

View File

@ -3,6 +3,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "applicationservice.h"
#include "applicationadaptor.h"
#include "instanceadaptor.h"
#include <QUuid>
@ -27,7 +28,7 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
QString objectPath{m_applicationPath.path() + "/" + QUuid::createUuid().toString()};
QSharedPointer<InstanceService> ins{new InstanceService{objectPath, ""}};
auto *ptr = ins.data();
if (registerObjectToDbus<decltype(ptr), InstanceAdaptor>(ptr, objectPath, getDBusInterface<InstanceAdaptor>())) {
if (registerObjectToDbus(new InstanceAdaptor(ptr), objectPath, getDBusInterface<InstanceAdaptor>())) {
m_Instances.insert(QDBusObjectPath{objectPath}, ins);
return QDBusObjectPath{objectPath};
}

View File

@ -33,9 +33,9 @@ public:
{
static_assert(std::is_invocable_v<F, QVariant>, "param type must be QVariant.");
QString objectPath{DDEApplicationManager1JobObjectPath + QUuid::createUuid().toString()};
QFuture<QVariantList> future = QtConcurrent::mappedReduced(
args.begin(), args.end(), func, &QVariantList::insert, QVariantList{}, QtConcurrent::ReduceOption::OrderedReduce);
QString objectPath{DDEApplicationManager1JobObjectPath + QUuid::createUuid().toString(QUuid::Id128)};
auto future = QtConcurrent::mappedReduced(
args.begin(), args.end(), func,qOverload<QVariantList::parameter_type>(&QVariantList::append), QVariantList{}, QtConcurrent::ReduceOption::OrderedReduce);
QSharedPointer<JobService> job{new JobService{future}};
auto path = QDBusObjectPath{objectPath};
{
@ -43,8 +43,8 @@ public:
m_jobs.insert(path, job); // Insertion is always successful
}
emit JobNew(path, source);
registerObjectToDbus<decltype(job.data()), JobAdaptor>(job.data(), objectPath, getDBusInterface<JobAdaptor>());
auto emitRemove = [this, job, path, future] {
registerObjectToDbus(new JobAdaptor(job.data()), objectPath, getDBusInterface<JobAdaptor>());
auto emitRemove = [this, job, path, future] (QVariantList value) {
decltype(m_jobs)::size_type removeCount{0};
{
QMutexLocker locker{&m_mutex};
@ -52,20 +52,21 @@ public:
}
// removeCount means m_jobs can't find value which corresponding with path
// and we shouldn't emit jobRemoved signal because this signal may already has been emit
if (removeCount == 0) {
if (removeCount == 0) {
qCritical() << "Job already has been removed: " << path.path();
return;
return value;
}
QString result{job->status()};
for (const auto &val : future.result()) {
if (val.canConvert<QDBusError>()) {
if (val.template canConvert<QDBusError>()) {
result = "failed";
}
break;
}
emit this->JobRemoved(path, result, future.result());
return value;
};
future.then(QtFuture::Launch::Sync, emitRemove);
future.then(emitRemove);
}
Q_SIGNALS:

View File

@ -1,18 +0,0 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "demo.h"
#include <iostream>
#include <QString>
void greet()
{
std::cout << QString{"Hello"}.toStdString() <<std::endl;
}
int main()
{
greet();
return 0;
}

View File

@ -110,18 +110,16 @@ std::optional<DesktopFile> DesktopFile::searchDesktopFile(const QString &desktop
auto components = path.split(QDir::separator()).toList();
auto it = std::find(components.cbegin(), components.cend(), "applications");
if (it == components.cend()) {
qWarning() << "fatal error: file location invalid";
err = ParseError::InvalidLocation;
return std::nullopt;
qWarning() << "custom location detected, Id wouldn't be generated.";
} else {
QString FileId;
++it;
while (it != components.cend())
FileId += (*(it++) + "-");
id = FileId.chopped(1);
}
QString FileId;
++it;
while (it != components.cend())
FileId += (*(it++) + "-");
id = FileId.chopped(1);
err = ParseError::NoError;
return DesktopFile{path,id};
return DesktopFile{std::move(path),std::move(id)};
}
ParseError DesktopEntry::parse(QTextStream& stream) noexcept
@ -239,13 +237,16 @@ QString DesktopEntry::Value::toIconString(bool &ok) const noexcept
bool DesktopEntry::Value::toBoolean(bool &ok) const noexcept
{
ok = true;
const auto& str = (*this)[defaultKeyStr];
if (str.compare("true"))
return true;
if (str.compare("false"))
return false;
ok = false;
const auto& str = (*this)[defaultKeyStr];
if (str == "true") {
ok = true;
return true;
}
if (str == "false") {
ok = true;
return false;
}
return false;
}
@ -262,3 +263,41 @@ QDebug operator<<(QDebug debug, const DesktopEntry::Value &v)
debug << static_cast<const QMap<QString,QString>&>(v);
return debug;
}
QDebug operator<<(QDebug debug, const ParseError &v)
{
QDebugStateSaver saver{debug};
QString errMsg;
switch (v) {
case ParseError::NoError:{
errMsg = "no error.";
break;
}
case ParseError::NotFound:{
errMsg = "file not found.";
break;
}
case ParseError::MismatchedFile:{
errMsg = "file type is mismatched.";
break;
}
case ParseError::InvalidLocation:{
errMsg = "file location is invalid, please check $XDG_DATA_DIRS.";
break;
}
case ParseError::OpenFailed:{
errMsg = "couldn't open the file.";
break;
}
case ParseError::GroupHeaderInvalid:{
errMsg = "groupHead syntax is invalid.";
break;
}
case ParseError::EntryKeyInvalid:{
errMsg = "key syntax is invalid.";
break;
}
}
debug << errMsg;
return debug;
}

View File

@ -1,5 +0,0 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
void greet();

View File

@ -14,7 +14,6 @@ constexpr static auto defaultKeyStr = "default";
enum class ParseError {
NoError,
NotFound,
FilePathEmpty,
MismatchedFile,
InvalidLocation,
OpenFailed,
@ -37,13 +36,13 @@ public:
friend QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
private:
QString unescape(const QString& str) const noexcept;
[[nodiscard]] QString unescape(const QString &str) const noexcept;
};
DesktopEntry() = default;
~DesktopEntry() = default;
ParseError parse(QTextStream& stream) noexcept;
QMap<QString, Value> group(const QString &key) const noexcept;
[[nodiscard]] ParseError parse(QTextStream& stream) noexcept;
[[nodiscard]] QMap<QString, Value> group(const QString &key) const noexcept;
private:
QMap<QString, QMap<QString, Value>> m_entryMap;
@ -54,13 +53,23 @@ private:
struct DesktopFile
{
const QString filePath;
const QString desktopId;
DesktopFile(const DesktopFile &) = default;
DesktopFile(DesktopFile &&) = default;
DesktopFile &operator=(const DesktopFile &) = default;
DesktopFile &operator=(DesktopFile &&) = default;
~DesktopFile() = default;
const QString &filePath() const { return m_filePath; }
const QString &desktopId() const { return m_desktopId; }
static std::optional<DesktopFile> searchDesktopFile(const QString &desktopFilePath, ParseError& err) noexcept;
private:
DesktopFile() = default;
DesktopFile(QString &&path,QString &&fileId):m_filePath(std::move(path)),m_desktopId(std::move(fileId)){}
QString m_filePath;
QString m_desktopId;
};
QDebug operator<<(QDebug debug, const DesktopEntry::Value& v);
QDebug operator<<(QDebug debug, const ParseError &v);

View File

@ -52,21 +52,7 @@ private:
QString m_busAddress;
};
template <typename T, typename U>
bool registerObjectToDbus(T parent, const QString &path, const QString &interface)
{
using service_type = std::remove_const_t<T>;
static_assert(std::is_pointer_v<service_type>, "param type must be a pointer");
static_assert(std::is_base_of_v<QObject, std::remove_pointer_t<T>> and
std::is_base_of_v<QObject, U>,
"param type must derive QObject");
auto &con = ApplicationManager1DBus::instance().CustomBus();
if (!con.registerObject(path, interface, new U{parent})) {
qCritical() << "register object failed:" << path << interface << con.lastError();
return false;
}
return true;
}
bool registerObjectToDbus(QObject* o, const QString &path, const QString &interface);
template <typename T>
QString getDBusInterface()

4
src/main.cpp Normal file
View File

@ -0,0 +1,4 @@
int main()
{
return 0;
}

11
src/utils.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "global.h"
bool registerObjectToDbus(QObject *o, const QString &path, const QString &interface)
{
auto &con = ApplicationManager1DBus::instance().CustomBus();
if (!con.registerObject(path, interface, o)) {
qCritical() << "register object failed:" << path << interface << con.lastError();
return false;
}
return true;
}