diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index 48f5293..0eeb857 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,48 +1,47 @@ find_package(Qt5 REQUIRED CONFIG COMPONENTS Test) include_directories(${libksysguard_SOURCE_DIR}) -if(Qt5WebEngineWidgets_FOUND) - # Process unit test - ecm_qt_declare_logging_category(processtest_debug_SRCS HEADER processcore_debug.h IDENTIFIER LIBKSYSGUARD_PROCESSCORE CATEGORY_NAME org.kde.libksysguard.processcore) - ecm_add_test(processtest.cpp ${processtest_debug_SRCS} TEST_NAME processtest - LINK_LIBRARIES KSysGuard::ProcessUi Qt5::Test) -endif() + +# Process unit test +ecm_qt_declare_logging_category(processtest_debug_SRCS HEADER processcore_debug.h IDENTIFIER LIBKSYSGUARD_PROCESSCORE CATEGORY_NAME org.kde.libksysguard.processcore) +ecm_add_test(processtest.cpp ${processtest_debug_SRCS} TEST_NAME processtest + LINK_LIBRARIES KSysGuard::ProcessUi Qt5::Test) if (KF5Plasma_FOUND) set(SIGNALPLOTTER_DEBUG_SRCS) ecm_qt_declare_logging_category(SIGNALPLOTTER_DEBUG_SRCS HEADER ksignalplotter_debug.h IDENTIFIER LIBKSYSGUARD_KSIGNALPLOTTER CATEGORY_NAME org.kde.libksysguard.ksignalplotter) ecm_add_test(signalplotterbenchmark.cpp ../signalplotter/ksignalplotter.cpp ${SIGNALPLOTTER_DEBUG_SRCS} TEST_NAME signalplotterbenchmark LINK_LIBRARIES KSysGuard::SignalPlotter Qt5::Test Qt5::Widgets KF5::IconThemes ) ecm_add_test(graphicssignalplotterbenchmark.cpp ../signalplotter/kgraphicssignalplotter.cpp ${SIGNALPLOTTER_DEBUG_SRCS} TEST_NAME graphicssignalplotterbenchmark LINK_LIBRARIES KSysGuard::SignalPlotter Qt5::Test Qt5::Widgets KF5::IconThemes KF5::Plasma ) ecm_add_test(signalplottertest.cpp ../signalplotter/ksignalplotter.cpp ${SIGNALPLOTTER_DEBUG_SRCS} TEST_NAME signalplottertest LINK_LIBRARIES KSysGuard::SignalPlotter Qt5::Test Qt5::Widgets KF5::IconThemes ) endif() ecm_add_test(chronotest.cpp TEST_NAME chronotest LINK_LIBRARIES Qt5::Test KF5::I18n ) ecm_add_test(formattertest.cpp LINK_LIBRARIES Qt5::Test KSysGuard::Formatter) # set( ksysguarddtest_SRCS ksysguarddtest.cpp ${libksysguard_SOURCE_DIR}/ksgrd/SensorAgent.cpp ${libksysguard_SOURCE_DIR}/ksgrd/SensorManager.cpp ${libksysguard_SOURCE_DIR}/ksgrd/SensorSocketAgent.cpp ${libksysguard_SOURCE_DIR}/ksgrd/SensorShellAgent.cpp) # # ecm_add_test(${ksysguarddtest_SRCS} # TEST_NAME "ksysguard-ksysguarddtest" # LINK_LIBRARIES # Qt5::Test # Qt5::Network # Qt5::Widgets # KF5::ConfigCore # KF5::CoreAddons # KF5::I18n # ) diff --git a/processcore/process_controller.cpp b/processcore/process_controller.cpp index ef9b462..9605d84 100644 --- a/processcore/process_controller.cpp +++ b/processcore/process_controller.cpp @@ -1,303 +1,298 @@ /* * This file is part of KSysGuard. * Copyright 2019 Arjen Hiemstra * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY 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 * along with this program. If not, see . */ #include "process_controller.h" #include #include #include #include #include "processes_local_p.h" #include "processcore_debug.h" using namespace KSysGuard; struct ApplyResult { ProcessController::Result resultCode = ProcessController::Result::Success; QVector unchanged; }; class ProcessController::Private { public: ApplyResult applyToPids(const QVector &pids, const std::function &function); ProcessController::Result runKAuthAction(const QString &actionId, const QVector &pids, const QVariantMap &options); QVector listToVector(const QList &list); QVector listToVector(const QVariantList &list); QWidget *widget; - - // Note: This instance is only to have access to the platform-specific code - // for sending signals, setting priority etc. Therefore, it should never be - // used to access information about processes. - static std::unique_ptr localProcesses; }; -std::unique_ptr ProcessController::Private::localProcesses; +// Note: This instance is only to have access to the platform-specific code +// for sending signals, setting priority etc. Therefore, it should never be +// used to access information about processes. +Q_GLOBAL_STATIC(ProcessesLocal, s_localProcesses); ProcessController::ProcessController(QObject* parent) : QObject(parent), d(new Private) { - if (!d->localProcesses) { - d->localProcesses = std::make_unique(); - } } KSysGuard::ProcessController::~ProcessController() { // Empty destructor needed for std::unique_ptr to incomplete class. } QWidget * KSysGuard::ProcessController::widget() const { return d->widget; } void KSysGuard::ProcessController::setWidget(QWidget* widget) { d->widget = widget; } ProcessController::Result ProcessController::sendSignal(const QVector& pids, int signal) { qCDebug(LIBKSYSGUARD_PROCESSCORE) << "Sending signal" << signal << "to" << pids; - auto result = d->applyToPids(pids, [this, signal](int pid) { return d->localProcesses->sendSignal(pid, signal); }); + auto result = d->applyToPids(pids, [this, signal](int pid) { return s_localProcesses->sendSignal(pid, signal); }); if (result.unchanged.isEmpty()) { return result.resultCode; } return d->runKAuthAction( QStringLiteral("org.kde.ksysguard.processlisthelper.sendsignal"), result.unchanged, { {QStringLiteral("signal"), signal} } ); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::sendSignal(const QList& pids, int signal) { return sendSignal(d->listToVector(pids), signal); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::sendSignal(const QVariantList &pids, int signal) { return sendSignal(d->listToVector(pids), signal); } ProcessController::Result ProcessController::setPriority(const QVector& pids, int priority) { - auto result = d->applyToPids(pids, [this, priority](int pid) { return d->localProcesses->setNiceness(pid, priority); }); + auto result = d->applyToPids(pids, [this, priority](int pid) { return s_localProcesses->setNiceness(pid, priority); }); if (result.unchanged.isEmpty()) { return result.resultCode; } return d->runKAuthAction( QStringLiteral("org.kde.ksysguard.processlisthelper.renice"), result.unchanged, { { QStringLiteral("nicevalue"), priority } } ); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::setPriority(const QList& pids, int priority) { return setPriority(d->listToVector(pids), priority); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::setPriority(const QVariantList &pids, int priority) { return setPriority(d->listToVector(pids), priority); } ProcessController::Result ProcessController::setCPUScheduler(const QVector& pids, Process::Scheduler scheduler, int priority) { if (scheduler == KSysGuard::Process::Other || scheduler == KSysGuard::Process::Batch) { priority = 0; } auto result = d->applyToPids(pids, [this, scheduler, priority](int pid) { - return d->localProcesses->setScheduler(pid, scheduler, priority); + return s_localProcesses->setScheduler(pid, scheduler, priority); }); if (result.unchanged.isEmpty()) { return result.resultCode; } return d->runKAuthAction( QStringLiteral("org.kde.ksysguard.processlisthelper.changecpuscheduler"), result.unchanged, {{QStringLiteral("cpuScheduler"), scheduler}, {QStringLiteral("cpuSchedulerPriority"), priority}} ); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::setCPUScheduler(const QList& pids, Process::Scheduler scheduler, int priority) { return setCPUScheduler(d->listToVector(pids), scheduler, priority); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::setCPUScheduler(const QVariantList &pids, Process::Scheduler scheduler, int priority) { return setCPUScheduler(d->listToVector(pids), scheduler, priority); } ProcessController::Result ProcessController::setIOScheduler(const QVector& pids, Process::IoPriorityClass priorityClass, int priority) { - if (!d->localProcesses->supportsIoNiceness()) { + if (!s_localProcesses->supportsIoNiceness()) { return Result::Unsupported; } if (priorityClass == KSysGuard::Process::None) { priorityClass = KSysGuard::Process::BestEffort; } if (priorityClass == KSysGuard::Process::Idle) { priority = 0; } auto result = d->applyToPids(pids, [this, priorityClass, priority](int pid) { - return d->localProcesses->setIoNiceness(pid, priorityClass, priority); + return s_localProcesses->setIoNiceness(pid, priorityClass, priority); }); if (result.unchanged.isEmpty()) { return result.resultCode; } return d->runKAuthAction( QStringLiteral("org.kde.ksysguard.processlisthelper.changeioscheduler"), result.unchanged, {{QStringLiteral("ioScheduler"), priorityClass}, {QStringLiteral("ioSchedulerPriority"), priority}} ); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::setIOScheduler(const QList& pids, Process::IoPriorityClass priorityClass, int priority) { return setIOScheduler(d->listToVector(pids), priorityClass, priority); } KSysGuard::ProcessController::Result KSysGuard::ProcessController::setIOScheduler(const QVariantList &pids, Process::IoPriorityClass priorityClass, int priority) { return setIOScheduler(d->listToVector(pids), priorityClass, priority); } QString ProcessController::resultToString(Result result) { switch(result) { case Result::Success: return i18n("Success"); case Result::InsufficientPermissions: return i18n("Insufficient permissions."); case Result::NoSuchProcess: return i18n("No matching process was found."); case Result::Unsupported: return i18n("Not supported on the current system."); case Result::UserCancelled: return i18n("The user cancelled."); case Result::Error: return i18n("An unspecified error occurred."); default: return i18n("An unknown error occurred."); } } ApplyResult KSysGuard::ProcessController::Private::applyToPids(const QVector& pids, const std::function& function) { ApplyResult result; - localProcesses->errorCode = KSysGuard::Processes::Unknown; + s_localProcesses->errorCode = KSysGuard::Processes::Unknown; for (auto pid : pids) { auto success = function(pid); if (!success) { - switch (localProcesses->errorCode) { + switch (s_localProcesses->errorCode) { case KSysGuard::Processes::InsufficientPermissions: case KSysGuard::Processes::Unknown: result.unchanged << pid; result.resultCode = Result::InsufficientPermissions; break; case Processes::InvalidPid: case Processes::ProcessDoesNotExistOrZombie: case Processes::InvalidParameter: result.resultCode = Result::NoSuchProcess; break; case Processes::NotSupported: result.resultCode = Result::Unsupported; break; default: result.resultCode = Result::Unknown; break; } } } return result; } ProcessController::Result ProcessController::Private::runKAuthAction(const QString& actionId, const QVector &pids, const QVariantMap& options) { KAuth::Action action(actionId); if (!action.isValid()) { qCWarning(LIBKSYSGUARD_PROCESSCORE) << "Executing KAuth action" << actionId << "failed because it is an invalid action"; return Result::InsufficientPermissions; } action.setParentWidget(widget); action.setHelperId(QStringLiteral("org.kde.ksysguard.processlisthelper")); const int processCount = pids.count(); for (int i = 0; i < processCount; ++i) { action.addArgument(QStringLiteral("pid%1").arg(i), pids.at(i)); } action.addArgument(QStringLiteral("pidcount"), processCount); for (auto itr = options.cbegin(); itr != options.cend(); ++itr) { action.addArgument(itr.key(), itr.value()); } KAuth::ExecuteJob *job = action.execute(); if(job->exec()) { return Result::Success; } else { if (job->error() == KAuth::ActionReply::UserCancelledError) { return Result::UserCancelled; } if (job->error() == KAuth::ActionReply::AuthorizationDeniedError) { return Result::InsufficientPermissions; } qCWarning(LIBKSYSGUARD_PROCESSCORE) << "Executing KAuth action" << actionId << "failed with error code" << job->error(); qCWarning(LIBKSYSGUARD_PROCESSCORE) << job->errorString(); return Result::Error; } } QVector KSysGuard::ProcessController::Private::listToVector(const QList& list) { QVector vector; std::transform(list.cbegin(), list.cend(), std::back_inserter(vector), [](long long entry) { return entry; }); return vector; } QVector KSysGuard::ProcessController::Private::listToVector(const QVariantList &list) { QVector vector; std::transform(list.cbegin(), list.cend(), std::back_inserter(vector), [](const QVariant &entry) { return entry.toInt(); }); return vector; }