test: add identify test
fix some bugs found in testing Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
		| @ -4,7 +4,7 @@ Upstream-Contact: UnionTech Software Technology Co., Ltd. <> | ||||
| Source: https://github.com/linuxdeepin/dde-application-manager | ||||
|  | ||||
| # README & DOC | ||||
| Files: README.md README.zh_CN.md docs/* | ||||
| Files: README.md README.zh_CN.md docs/* examples/launchApp/README.md | ||||
| Copyright: UnionTech Software Technology Co., Ltd. | ||||
| License: CC-BY-4.0 | ||||
|  | ||||
|  | ||||
| @ -17,6 +17,8 @@ | ||||
| #include <thread> | ||||
| #include "constant.h" | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| enum class ExitCode { SystemdError = -3, InvalidInput = -2, InternalError = -1, Done = 0, Waiting = 1 }; | ||||
|  | ||||
| struct JobRemoveResult | ||||
| @ -29,7 +31,7 @@ struct JobRemoveResult | ||||
| using msg_ptr = sd_bus_message *; | ||||
| using bus_ptr = sd_bus *; | ||||
|  | ||||
| static ExitCode fromString(const std::string &str) | ||||
| ExitCode fromString(const std::string &str) | ||||
| { | ||||
|     if (str == "done") { | ||||
|         return ExitCode::Done; | ||||
| @ -50,7 +52,7 @@ static ExitCode fromString(const std::string &str) | ||||
|     __builtin_unreachable(); | ||||
| } | ||||
|  | ||||
| static ExitCode fromString(const char *str) | ||||
| ExitCode fromString(const char *str) | ||||
| { | ||||
|     if (!str) { | ||||
|         return ExitCode::Waiting; | ||||
| @ -59,7 +61,7 @@ static ExitCode fromString(const char *str) | ||||
|     return fromString(tmp); | ||||
| } | ||||
|  | ||||
| [[noreturn]] static void releaseRes(sd_bus_error &error, msg_ptr &msg, bus_ptr &bus, ExitCode ret) | ||||
| [[noreturn]] void releaseRes(sd_bus_error &error, msg_ptr &msg, bus_ptr &bus, ExitCode ret) | ||||
| { | ||||
|     sd_bus_error_free(&error); | ||||
|     sd_bus_message_unref(msg); | ||||
| @ -68,7 +70,7 @@ static ExitCode fromString(const char *str) | ||||
|     std::exit(static_cast<int>(ret)); | ||||
| } | ||||
|  | ||||
| static int processExecStart(msg_ptr &msg, const std::deque<std::string_view> &execArgs) | ||||
| int processExecStart(msg_ptr &msg, const std::deque<std::string_view> &execArgs) | ||||
| { | ||||
|     int ret; | ||||
|     if (ret = sd_bus_message_append(msg, "s", "ExecStart"); ret < 0) { | ||||
| @ -139,7 +141,7 @@ static int processExecStart(msg_ptr &msg, const std::deque<std::string_view> &ex | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int processKVPair(msg_ptr &msg, const std::map<std::string_view, std::string_view> &props) | ||||
| int processKVPair(msg_ptr &msg, const std::map<std::string_view, std::string_view> &props) | ||||
| { | ||||
|     int ret; | ||||
|     if (!props.empty()) { | ||||
| @ -155,7 +157,7 @@ static int processKVPair(msg_ptr &msg, const std::map<std::string_view, std::str | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static std::string cmdParse(msg_ptr &msg, std::deque<std::string_view> &&cmdLines) | ||||
| std::string cmdParse(msg_ptr &msg, std::deque<std::string_view> &&cmdLines) | ||||
| { | ||||
|     std::string serviceName{"internalError"}; | ||||
|     std::map<std::string_view, std::string_view> props; | ||||
| @ -241,6 +243,11 @@ static std::string cmdParse(msg_ptr &msg, std::deque<std::string_view> &&cmdLine | ||||
|         return serviceName; | ||||
|     } | ||||
|  | ||||
|     if (ret = sd_bus_message_append(msg, "(sv)", "Slice", "s", "app.slice"); ret < 0) { | ||||
|         sd_journal_perror("append application slice failed."); | ||||
|         return serviceName; | ||||
|     } | ||||
|  | ||||
|     if (ret = sd_bus_message_open_container(msg, SD_BUS_TYPE_STRUCT, "sv"); ret < 0) { | ||||
|         sd_journal_perror("open struct failed."); | ||||
|         return serviceName; | ||||
| @ -300,7 +307,7 @@ int jobRemovedReceiver(sd_bus_message *m, void *userdata, sd_bus_error *ret_erro | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int process_dbus_message(sd_bus *bus) | ||||
| int process_dbus_message(sd_bus *bus) | ||||
| { | ||||
|     int ret; | ||||
|     ret = sd_bus_process(bus, nullptr); | ||||
| @ -322,6 +329,8 @@ static int process_dbus_message(sd_bus *bus) | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| }  // namespace | ||||
|  | ||||
| int main(int argc, const char *argv[]) | ||||
| { | ||||
|     sd_bus_error error{SD_BUS_ERROR_NULL}; | ||||
|  | ||||
| @ -9,12 +9,14 @@ | ||||
| #include "dbus/applicationmanager1service.h" | ||||
| #include "cgroupsidentifier.h" | ||||
|  | ||||
| static void registerComplexDbusType() | ||||
| namespace { | ||||
| void registerComplexDbusType() | ||||
| { | ||||
|     qDBusRegisterMetaType<QMap<QString, QDBusUnixFileDescriptor>>(); | ||||
|     qDBusRegisterMetaType<QMap<uint, QMap<QString, QDBusUnixFileDescriptor>>>(); | ||||
|     qDBusRegisterMetaType<IconMap>(); | ||||
| } | ||||
| }  // namespace | ||||
|  | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
| @ -22,7 +24,7 @@ int main(int argc, char *argv[]) | ||||
|  | ||||
|     auto &bus = ApplicationManager1DBus::instance(); | ||||
|     bus.initGlobalServerBus(DBusType::Session); | ||||
|     bus.setDestBus(""); | ||||
|     bus.setDestBus(); | ||||
|     auto &AMBus = bus.globalServerBus(); | ||||
|  | ||||
|     registerComplexDbusType(); | ||||
|  | ||||
							
								
								
									
										5
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							| @ -3,6 +3,11 @@ Section: devel | ||||
| Priority: optional | ||||
| Maintainer: Chen Linxuan <chenlinxuan@uniontech.com> | ||||
| Build-Depends: | ||||
|  cmake, | ||||
|  libsystemd-dev, | ||||
|  qt6-base-dev, | ||||
|  libgtest-dev, | ||||
|  pkg-config | ||||
| Standards-Version: 4.1.3 | ||||
| Homepage: https://github.com/linuxdeepin/dde-application-manager | ||||
| Package: dde-application-manager-reborn | ||||
|  | ||||
| @ -16,14 +16,13 @@ IdentifyRet CGroupsIdentifier::Identify(pid_t pid) | ||||
|         qWarning() << "open " << AppCgroupPath << "failed: " << AppCgroupFile.errorString(); | ||||
|         return {}; | ||||
|     } | ||||
|     auto appInstance = parseCGroupsPath( | ||||
|         AppCgroupFile.readAll().split(':').last().trimmed());  // FIXME: support CGroup version detection and multi-line parsing | ||||
|     auto appInstanceComponent = appInstance.split('@'); | ||||
|     if (appInstanceComponent.count() != 2) { | ||||
|         qWarning() << "Application Instance format is invalid." << appInstanceComponent; | ||||
|         return {}; | ||||
|     } | ||||
|     return {appInstanceComponent.first(), appInstanceComponent.last()}; | ||||
|     auto UnitStr = parseCGroupsPath(QString::fromLocal8Bit(AppCgroupFile.readAll()) | ||||
|                                         .split(':', Qt::SkipEmptyParts) | ||||
|                                         .last() | ||||
|                                         .trimmed());  // FIXME: support CGroup version detection and multi-line parsing | ||||
|  | ||||
|     auto [appId, InstanceId] = processUnitName(UnitStr); | ||||
|     return {std::move(appId), std::move(InstanceId)}; | ||||
| } | ||||
|  | ||||
| QString CGroupsIdentifier::parseCGroupsPath(const QString &CGP) noexcept | ||||
| @ -32,8 +31,7 @@ QString CGroupsIdentifier::parseCGroupsPath(const QString &CGP) noexcept | ||||
|         qWarning() << "CGroupPath is empty."; | ||||
|         return {}; | ||||
|     } | ||||
|     auto unescapedCGP = unescapeString(CGP); | ||||
|     auto CGPSlices = unescapedCGP.split('/'); | ||||
|     auto CGPSlices = CGP.split('/', Qt::SkipEmptyParts); | ||||
|  | ||||
|     if (CGPSlices.first() != "user.slice") { | ||||
|         qWarning() << "unrecognized process."; | ||||
| @ -51,7 +49,7 @@ QString CGroupsIdentifier::parseCGroupsPath(const QString &CGP) noexcept | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     auto appInstance = CGPSlices.last().split('.').first(); | ||||
|     auto appInstance = CGPSlices.last(); | ||||
|     if (appInstance.isEmpty()) { | ||||
|         qWarning() << "get AppId failed."; | ||||
|         return {}; | ||||
|  | ||||
| @ -90,41 +90,6 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie | ||||
|             }); | ||||
| } | ||||
|  | ||||
| QPair<QString, QString> ApplicationManager1Service::processUnitName(const QString &unitName) noexcept | ||||
| { | ||||
|     QString instanceId; | ||||
|     QString applicationId; | ||||
|  | ||||
|     if (unitName.endsWith(".service")) { | ||||
|         auto lastDotIndex = unitName.lastIndexOf('.'); | ||||
|         auto app = unitName.sliced(0, lastDotIndex - 1);  // remove suffix | ||||
|  | ||||
|         if (app.contains('@')) { | ||||
|             auto atIndex = app.indexOf('@'); | ||||
|             instanceId = app.sliced(atIndex + 1); | ||||
|             app.remove(atIndex, instanceId.length() + 1); | ||||
|         } | ||||
|  | ||||
|         applicationId = app.split('-').last();  // drop launcher if it exists. | ||||
|     } else if (unitName.endsWith(".scope")) { | ||||
|         auto lastDotIndex = unitName.lastIndexOf('.'); | ||||
|         auto app = unitName.sliced(0, lastDotIndex - 1); | ||||
|  | ||||
|         auto components = app.split('-'); | ||||
|         instanceId = components.takeLast(); | ||||
|         applicationId = components.takeLast(); | ||||
|     } else { | ||||
|         qDebug() << "it's not service or scope:" << unitName << "ignore."; | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     if (instanceId.isEmpty()) { | ||||
|         instanceId = QUuid::createUuid().toString(QUuid::Id128); | ||||
|     } | ||||
|  | ||||
|     return qMakePair(unescapeApplicationId(applicationId), std::move(instanceId)); | ||||
| } | ||||
|  | ||||
| QList<QDBusObjectPath> ApplicationManager1Service::list() const | ||||
| { | ||||
|     return m_applicationList.keys(); | ||||
|  | ||||
| @ -62,8 +62,6 @@ private: | ||||
|     std::unique_ptr<Identifier> m_identifier; | ||||
|     QScopedPointer<JobManager1Service> m_jobManager{nullptr}; | ||||
|     QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> m_applicationList; | ||||
|  | ||||
|     static QPair<QString, QString> processUnitName(const QString &serviceName) noexcept; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @ -64,7 +64,7 @@ public Q_SLOTS: | ||||
| private: | ||||
|     friend class ApplicationManager1Service; | ||||
|     template <typename T> | ||||
|     ApplicationService(T &&source, ApplicationManager1Service *parent) | ||||
|     explicit ApplicationService(T &&source, ApplicationManager1Service *parent = nullptr) | ||||
|         : m_parent(parent) | ||||
|         , m_desktopSource(std::forward<T>(source)) | ||||
|     { | ||||
| @ -84,7 +84,9 @@ private: | ||||
|             m_isPersistence = true; | ||||
|             sourceFile.setFileName(m_desktopSource.m_file.filePath()); | ||||
|             if (!sourceFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) { | ||||
| #ifndef DEBUG_MODE | ||||
|                 qCritical() << "desktop file can't open:" << m_desktopSource.m_file.filePath() << sourceFile.errorString(); | ||||
| #endif | ||||
|                 return; | ||||
|             } | ||||
|             sourceStream.setDevice(&sourceFile); | ||||
|  | ||||
							
								
								
									
										58
									
								
								src/global.h
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								src/global.h
									
									
									
									
									
								
							| @ -18,6 +18,7 @@ | ||||
| #include <QRegularExpression> | ||||
| #include <QDBusObjectPath> | ||||
| #include <unistd.h> | ||||
| #include <QUuid> | ||||
| #include "constant.h" | ||||
| #include "config.h" | ||||
|  | ||||
| @ -143,7 +144,7 @@ public: | ||||
|         return m_destConnection.value(); | ||||
|     } | ||||
|  | ||||
|     void setDestBus(const QString &destAddress) | ||||
|     void setDestBus(const QString &destAddress = "") | ||||
|     { | ||||
|         if (m_destConnection) { | ||||
|             m_destConnection->disconnectFromBus(ApplicationManagerDestDBusName); | ||||
| @ -206,26 +207,6 @@ inline QLocale getUserLocale() | ||||
|     return QLocale::system();  // current use env | ||||
| } | ||||
|  | ||||
| inline QString unescapeString(const QString &input) | ||||
| { | ||||
|     QRegularExpression regex("\\\\x([0-9A-Fa-f]{2})"); | ||||
|     QRegularExpressionMatchIterator it = regex.globalMatch(input); | ||||
|     QString output{input}; | ||||
|  | ||||
|     while (it.hasNext()) { | ||||
|         QRegularExpressionMatch match = it.next(); | ||||
|         bool ok; | ||||
|         // Get the hexadecimal value from the match and convert it to a number. | ||||
|         int asciiValue = match.captured(1).toInt(&ok, 16); | ||||
|         if (ok) { | ||||
|             // Convert the ASCII value to a QChar and perform the replacement. | ||||
|             output.replace(match.capturedStart(), match.capturedLength(), QChar(asciiValue)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return output; | ||||
| } | ||||
|  | ||||
| inline QString escapeToObjectPath(const QString &str) | ||||
| { | ||||
|     if (str.isEmpty()) { | ||||
| @ -333,4 +314,39 @@ inline QStringList getXDGDataDirs() | ||||
|     return XDGDataDirs; | ||||
| } | ||||
|  | ||||
| inline QPair<QString, QString> processUnitName(const QString &unitName) | ||||
| { | ||||
|     QString instanceId; | ||||
|     QString applicationId; | ||||
|  | ||||
|     if (unitName.endsWith(".service")) { | ||||
|         auto lastDotIndex = unitName.lastIndexOf('.'); | ||||
|         auto app = unitName.sliced(0, lastDotIndex);  // remove suffix | ||||
|  | ||||
|         if (app.contains('@')) { | ||||
|             auto atIndex = app.indexOf('@'); | ||||
|             instanceId = app.sliced(atIndex + 1); | ||||
|             app.remove(atIndex, instanceId.length() + 1); | ||||
|         } | ||||
|  | ||||
|         applicationId = app.split('-').last();  // drop launcher if it exists. | ||||
|     } else if (unitName.endsWith(".scope")) { | ||||
|         auto lastDotIndex = unitName.lastIndexOf('.'); | ||||
|         auto app = unitName.sliced(0, lastDotIndex); | ||||
|  | ||||
|         auto components = app.split('-'); | ||||
|         instanceId = components.takeLast(); | ||||
|         applicationId = components.takeLast(); | ||||
|     } else { | ||||
|         qDebug() << "it's not service or scope:" << unitName << "ignore."; | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     if (instanceId.isEmpty()) { | ||||
|         instanceId = QUuid::createUuid().toString(QUuid::Id128); | ||||
|     } | ||||
|  | ||||
|     return qMakePair(unescapeApplicationId(applicationId), std::move(instanceId)); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @ -18,7 +18,16 @@ target_link_libraries(${BIN_NAME} PRIVATE | ||||
|     dde_am_static | ||||
| ) | ||||
|  | ||||
| target_compile_options(${BIN_NAME} PRIVATE "-fno-access-control") | ||||
| target_compile_options(${BIN_NAME} PRIVATE | ||||
|     -fno-access-control | ||||
|     -fsanitize=undefined | ||||
|     -fsanitize=address | ||||
| ) | ||||
|  | ||||
| target_link_options(${BIN_NAME} PRIVATE | ||||
|     -fsanitize=undefined | ||||
|     -fsanitize=address | ||||
| ) | ||||
|  | ||||
| add_test( | ||||
|     NAME UnitTest | ||||
|  | ||||
							
								
								
									
										154
									
								
								tests/ut_applicationmanager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								tests/ut_applicationmanager.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,154 @@ | ||||
| // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. | ||||
| // | ||||
| // SPDX-License-Identifier: LGPL-3.0-or-later | ||||
|  | ||||
| #include "dbus/applicationmanager1service.h" | ||||
| #include "dbus/applicationservice.h" | ||||
| #include "cgroupsidentifier.h" | ||||
| #include "constant.h" | ||||
| #include <gtest/gtest.h> | ||||
| #include <QDBusConnection> | ||||
| #include <QSharedPointer> | ||||
| #include <sys/syscall.h> | ||||
| #include <QProcess> | ||||
| #include <thread> | ||||
| #include <chrono> | ||||
| #include <QDBusUnixFileDescriptor> | ||||
|  | ||||
| namespace { | ||||
| int pidfd_open(pid_t pid, uint flags) | ||||
| { | ||||
|     return syscall(SYS_pidfd_open, pid, flags); | ||||
| } | ||||
| }  // namespace | ||||
|  | ||||
| class TestApplicationManager : public testing::Test | ||||
| { | ||||
| public: | ||||
|     static void SetUpTestCase() | ||||
|     { | ||||
|         auto &bus = ApplicationManager1DBus::instance(); | ||||
|         bus.initGlobalServerBus(DBusType::Session); | ||||
|         bus.setDestBus(); | ||||
|  | ||||
|         m_am = new ApplicationManager1Service{std::make_unique<CGroupsIdentifier>(), bus.globalServerBus()}; | ||||
|  | ||||
|         DesktopFile file{"/usr/share/applications/test-Application.desktop", "test-Application", 0}; | ||||
|         QSharedPointer<ApplicationService> app = QSharedPointer<ApplicationService>::create(std::move(file)); | ||||
|         QSharedPointer<InstanceService> instance = | ||||
|             QSharedPointer<InstanceService>::create(InstancePath.path().split('/').last(), ApplicationPath.path(), QString{"/"}); | ||||
|         app->m_Instances.insert(InstancePath, instance); | ||||
|         m_am->m_applicationList.insert(ApplicationPath, app); | ||||
|     } | ||||
|  | ||||
|     static void TearDownTestCase() { m_am->deleteLater(); } | ||||
|  | ||||
|     static inline ApplicationManager1Service *m_am{nullptr}; | ||||
|     const static inline QDBusObjectPath ApplicationPath{DDEApplicationManager1ApplicationObjectPath + | ||||
|                                                         QUuid::createUuid().toString(QUuid::Id128)}; | ||||
|     const static inline QDBusObjectPath InstancePath{DDEApplicationManager1InstanceObjectPath + | ||||
|                                                      QUuid::createUuid().toString(QUuid::Id128)}; | ||||
| }; | ||||
|  | ||||
| TEST_F(TestApplicationManager, list) | ||||
| { | ||||
|     auto lists = m_am->list(); | ||||
|     EXPECT_EQ(lists.first(), ApplicationPath); | ||||
| } | ||||
|  | ||||
| TEST_F(TestApplicationManager, application) | ||||
| { | ||||
|     EXPECT_EQ(m_am->Application("test-Application"), ApplicationPath); | ||||
| } | ||||
|  | ||||
| TEST_F(TestApplicationManager, identifyService) | ||||
| { | ||||
|     using namespace std::chrono_literals; | ||||
|     // for service unit | ||||
|     auto workingDir = QDir::cleanPath(QDir::current().absolutePath() + QDir::separator() + ".." + QDir::separator() + "tools"); | ||||
|     QFile pidFile{workingDir + QDir::separator() + "pid.txt"}; | ||||
|     if (pidFile.exists()) { | ||||
|         ASSERT_TRUE(pidFile.remove()); | ||||
|     } | ||||
|  | ||||
|     QProcess fakeServiceProc; | ||||
|     fakeServiceProc.setWorkingDirectory(workingDir); | ||||
|     auto InstanceId = InstancePath.path().split('/').last(); | ||||
|     fakeServiceProc.start("/usr/bin/systemd-run", | ||||
|                           {{QString{R"(--unit=app-DDE-test\x2dApplication@%1.service)"}.arg(InstanceId)}, | ||||
|                            {"--user"}, | ||||
|                            {QString{"--working-directory=%1"}.arg(workingDir)}, | ||||
|                            {"--slice=app.slice"}, | ||||
|                            {"./fake-process.sh"}}); | ||||
|     fakeServiceProc.waitForFinished(); | ||||
|     if (fakeServiceProc.exitStatus() != QProcess::ExitStatus::NormalExit) { | ||||
|         GTEST_SKIP() << "invoke systemd-run failed."; | ||||
|     } | ||||
|  | ||||
|     std::this_thread::sleep_for(100ms); | ||||
|  | ||||
|     auto success = pidFile.open(QFile::ReadOnly | QFile::Text | QFile::ExistingOnly); | ||||
|     EXPECT_TRUE(success); | ||||
|  | ||||
|     if (!success) { | ||||
|         qWarning() << pidFile.errorString(); | ||||
|         fakeServiceProc.terminate(); | ||||
|         ASSERT_TRUE(false); | ||||
|     } | ||||
|  | ||||
|     bool ok{false}; | ||||
|     auto fakePid = pidFile.readLine().toInt(&ok); | ||||
|     ASSERT_TRUE(ok); | ||||
|  | ||||
|     auto pidfd = pidfd_open(fakePid, 0); | ||||
|     ASSERT_TRUE(pidfd > 0) << std::strerror(errno); | ||||
|     QDBusObjectPath application; | ||||
|     QDBusObjectPath application_instance; | ||||
|     auto appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, application, application_instance); | ||||
|     EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString()); | ||||
|     EXPECT_EQ(application.path().toStdString(), ApplicationPath.path().toStdString()); | ||||
|     EXPECT_EQ(application_instance.path().toStdString(), InstancePath.path().toStdString()); | ||||
|     close(pidfd); | ||||
|  | ||||
|     if (pidFile.exists()) { | ||||
|         pidFile.remove(); | ||||
|     } | ||||
|  | ||||
|     // for scope unit | ||||
|     ASSERT_TRUE(QProcess::startDetached("/usr/bin/systemd-run", | ||||
|                                         {{"--scope"}, | ||||
|                                          {QString{R"(--unit=app-DDE-test\x2dApplication-%1.scope)"}.arg(InstanceId)}, | ||||
|                                          {"--user"}, | ||||
|                                          {QString{"--working-directory=%1"}.arg(workingDir)}, | ||||
|                                          {"--slice=app.slice"}, | ||||
|                                          {"./fake-process.sh"}, | ||||
|                                          {"Scope"}}, | ||||
|                                         workingDir)); | ||||
|  | ||||
|     std::this_thread::sleep_for(100ms); | ||||
|  | ||||
|     success = pidFile.open(QFile::ReadOnly | QFile::Text | QFile::ExistingOnly); | ||||
|     EXPECT_TRUE(success); | ||||
|  | ||||
|     if (!success) { | ||||
|         qWarning() << pidFile.errorString(); | ||||
|         ASSERT_TRUE(false); | ||||
|     } | ||||
|  | ||||
|     ok = false; | ||||
|     fakePid = pidFile.readLine().toInt(&ok); | ||||
|     ASSERT_TRUE(ok); | ||||
|  | ||||
|     pidfd = pidfd_open(fakePid, 0); | ||||
|     ASSERT_TRUE(pidfd > 0) << std::strerror(errno); | ||||
|  | ||||
|     appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, application, application_instance); | ||||
|     EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString()); | ||||
|     EXPECT_EQ(application.path().toStdString(), ApplicationPath.path().toStdString()); | ||||
|     EXPECT_EQ(application_instance.path().toStdString(), InstancePath.path().toStdString()); | ||||
|     close(pidfd); | ||||
|  | ||||
|     if (pidFile.exists()) { | ||||
|         pidFile.remove(); | ||||
|     } | ||||
| } | ||||
| @ -30,8 +30,6 @@ public: | ||||
|  | ||||
|     static void TearDownTestCase() { qputenv("XDG_DATA_DIRS", env); } | ||||
|  | ||||
|     void SetUp() override {} | ||||
|     void TearDown() override {} | ||||
|     QSharedPointer<DesktopFile> file() { return m_file; } | ||||
|  | ||||
| private: | ||||
|  | ||||
| @ -43,5 +43,5 @@ TEST_F(TestJobManager, addJob) | ||||
|             return QVariant::fromValue(true); | ||||
|         }, | ||||
|         args); | ||||
|     QThread::sleep(1);  // force wait | ||||
|     QThreadPool::globalInstance()->waitForDone(); | ||||
| } | ||||
|  | ||||
							
								
								
									
										9
									
								
								tools/fake-process.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										9
									
								
								tools/fake-process.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,9 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. | ||||
| # | ||||
| # SPDX-License-Identifier: LGPL-3.0-or-later | ||||
|  | ||||
| echo $$ > pid.txt | ||||
| sleep 1s | ||||
| exit 0 | ||||
| @ -1,6 +1,6 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. | ||||
| # SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. | ||||
| # | ||||
| # SPDX-License-Identifier: LGPL-3.0-or-later | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user