Make bash completion faster by requesting only config
This commit is contained in:
parent
6be44cc93f
commit
914aac6e39
|
@ -216,14 +216,23 @@ int Application::loadConfig()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Application::waitForConnected(int timeout)
|
||||
bool Application::waitForConnected(int timeout)
|
||||
{
|
||||
using namespace TestUtilities;
|
||||
bool isConnected = m_connection.isConnected();
|
||||
const function<void(SyncthingStatus)> checkStatus([this, &isConnected](SyncthingStatus) { isConnected = m_connection.isConnected(); });
|
||||
waitForSignals(bind(static_cast<void (SyncthingConnection::*)(SyncthingConnectionSettings &)>(&SyncthingConnection::reconnect), ref(m_connection),
|
||||
ref(m_settings)),
|
||||
timeout, signalInfo(&m_connection, &SyncthingConnection::statusChanged, checkStatus, &isConnected));
|
||||
return waitForSignalsOrFail(bind(static_cast<void (SyncthingConnection::*)(SyncthingConnectionSettings &)>(&SyncthingConnection::reconnect),
|
||||
ref(m_connection), ref(m_settings)),
|
||||
timeout, signalInfo(&m_connection, &SyncthingConnection::error),
|
||||
signalInfo(&m_connection, &SyncthingConnection::statusChanged, checkStatus, &isConnected));
|
||||
}
|
||||
|
||||
bool Application::waitForConfig(int timeout)
|
||||
{
|
||||
using namespace TestUtilities;
|
||||
return waitForSignalsOrFail(bind(&SyncthingConnection::requestConfig, ref(m_connection)), timeout,
|
||||
signalInfo(&m_connection, &SyncthingConnection::error), signalInfo(&m_connection, &SyncthingConnection::newConfig),
|
||||
signalInfo(&m_connection, &SyncthingConnection::newDirs), signalInfo(&m_connection, &SyncthingConnection::newDevices));
|
||||
}
|
||||
|
||||
void Application::handleStatusChanged(SyncthingStatus newStatus)
|
||||
|
@ -723,9 +732,10 @@ void Application::initDirCompletion(Argument &arg, const ArgumentOccurrence &)
|
|||
}
|
||||
// load config and wait for connected
|
||||
loadConfig();
|
||||
waitForConnected(2000);
|
||||
waitForConfig(2000);
|
||||
// set directory IDs as completion values
|
||||
arg.setPreDefinedCompletionValues(m_connection.directoryIds().join(QChar(' ')).toUtf8().data());
|
||||
m_dirCompletion = m_connection.directoryIds().join(QChar(' ')).toUtf8();
|
||||
arg.setPreDefinedCompletionValues(m_dirCompletion.data());
|
||||
}
|
||||
|
||||
void Application::initDevCompletion(Argument &arg, const ArgumentOccurrence &)
|
||||
|
@ -736,7 +746,7 @@ void Application::initDevCompletion(Argument &arg, const ArgumentOccurrence &)
|
|||
}
|
||||
// load config and wait for connected
|
||||
loadConfig();
|
||||
waitForConnected(2000);
|
||||
waitForConfig(2000);
|
||||
// set device IDs and names as completion values
|
||||
QStringList completionValues;
|
||||
const size_t valueCount = m_connection.devInfo().size() << 2;
|
||||
|
@ -747,7 +757,8 @@ void Application::initDevCompletion(Argument &arg, const ArgumentOccurrence &)
|
|||
for (const SyncthingDev &dev : m_connection.devInfo()) {
|
||||
completionValues << dev.id << dev.name;
|
||||
}
|
||||
arg.setPreDefinedCompletionValues(completionValues.join(QChar(' ')).toUtf8().data());
|
||||
m_devCompletion = completionValues.join(QChar(' ')).toUtf8();
|
||||
arg.setPreDefinedCompletionValues(m_devCompletion.data());
|
||||
}
|
||||
|
||||
RelevantDir Application::findDirectory(const QString &dirIdentifier)
|
||||
|
|
|
@ -53,7 +53,8 @@ private slots:
|
|||
|
||||
private:
|
||||
int loadConfig();
|
||||
void waitForConnected(int timeout);
|
||||
bool waitForConnected(int timeout);
|
||||
bool waitForConfig(int timeout);
|
||||
void requestLog(const ArgumentOccurrence &);
|
||||
void requestShutdown(const ArgumentOccurrence &);
|
||||
void requestRestart(const ArgumentOccurrence &);
|
||||
|
@ -84,6 +85,8 @@ private:
|
|||
std::vector<RelevantDir> m_relevantDirs;
|
||||
std::vector<const Data::SyncthingDev *> m_relevantDevs;
|
||||
RelevantDir m_pwd;
|
||||
QByteArray m_dirCompletion;
|
||||
QByteArray m_devCompletion;
|
||||
int m_idleDuration;
|
||||
int m_idleTimeout;
|
||||
bool m_argsRead;
|
||||
|
|
|
@ -182,7 +182,7 @@ void SyncthingConnection::connect(SyncthingConnectionSettings &connectionSetting
|
|||
*/
|
||||
void SyncthingConnection::disconnect()
|
||||
{
|
||||
m_reconnecting = m_hasConfig = m_hasStatus = false;
|
||||
m_reconnecting = m_hasConfig = m_hasStatus = m_keepPolling = false;
|
||||
m_autoReconnectTries = 0;
|
||||
abortAllRequests();
|
||||
}
|
||||
|
@ -1007,9 +1007,15 @@ void SyncthingConnection::readConfig()
|
|||
}
|
||||
|
||||
m_rawConfig = replyDoc.object();
|
||||
emit newConfig(m_rawConfig);
|
||||
m_hasConfig = true;
|
||||
concludeReadingConfigAndStatus();
|
||||
emit newConfig(m_rawConfig);
|
||||
|
||||
if (m_keepPolling) {
|
||||
concludeReadingConfigAndStatus();
|
||||
} else {
|
||||
readDevs(m_rawConfig.value(QStringLiteral("devices")).toArray());
|
||||
readDirs(m_rawConfig.value(QStringLiteral("folders")).toArray());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
|
@ -1124,7 +1130,10 @@ void SyncthingConnection::readStatus()
|
|||
emitMyIdChanged(replyDoc.object().value(QStringLiteral("myID")).toString());
|
||||
// other values are currently not interesting
|
||||
m_hasStatus = true;
|
||||
concludeReadingConfigAndStatus();
|
||||
|
||||
if (m_keepPolling) {
|
||||
concludeReadingConfigAndStatus();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QNetworkReply::OperationCanceledError:
|
||||
|
|
|
@ -152,6 +152,16 @@ public Q_SLOTS:
|
|||
void shutdown();
|
||||
void considerAllNotificationsRead();
|
||||
|
||||
void requestConfig();
|
||||
void requestStatus();
|
||||
void requestErrors();
|
||||
void requestConnections();
|
||||
void requestClearingErrors();
|
||||
void requestDirStatistics();
|
||||
void requestDirStatus(const QString &dirId);
|
||||
void requestCompletion(const QString &devId, const QString &dirId);
|
||||
void requestDeviceStatistics();
|
||||
|
||||
Q_SIGNALS:
|
||||
void newConfig(const QJsonObject &config);
|
||||
void newDirs(const std::vector<SyncthingDir> &dirs);
|
||||
|
@ -177,16 +187,6 @@ Q_SIGNALS:
|
|||
void shutdownTriggered();
|
||||
|
||||
private Q_SLOTS:
|
||||
void requestConfig();
|
||||
void requestStatus();
|
||||
void requestConnections();
|
||||
void requestErrors();
|
||||
void requestClearingErrors();
|
||||
void requestDirStatistics();
|
||||
void requestDirStatus(const QString &dirId);
|
||||
void requestCompletion(const QString &devId, const QString &dirId);
|
||||
|
||||
void requestDeviceStatistics();
|
||||
void requestEvents();
|
||||
void abortAllRequests();
|
||||
|
||||
|
|
|
@ -103,6 +103,17 @@ private:
|
|||
*/
|
||||
template <typename Signal, typename Handler> class SignalInfo {
|
||||
public:
|
||||
/*!
|
||||
* \brief Constructs a dummy SignalInfo which will never be considered emitted.
|
||||
*/
|
||||
SignalInfo()
|
||||
: m_sender(nullptr)
|
||||
, m_signal(nullptr)
|
||||
, m_correctSignalEmitted(nullptr)
|
||||
, m_signalEmitted(false)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a SignalInfo with handler and automatically connects the handler to the signal.
|
||||
* \param sender Specifies the object which will emit \a signal.
|
||||
|
@ -182,6 +193,9 @@ public:
|
|||
*/
|
||||
void connectToLoop(QEventLoop *loop) const
|
||||
{
|
||||
if (!m_sender) {
|
||||
return;
|
||||
}
|
||||
QObject::disconnect(m_loopConnection);
|
||||
m_loopConnection = QObject::connect(m_sender, m_signal, loop, &QEventLoop::quit, Qt::DirectConnection);
|
||||
#ifndef SYNCTHINGTESTHELPER_FOR_CLI
|
||||
|
@ -205,12 +219,28 @@ private:
|
|||
* \brief Constructs a new SignalInfo.
|
||||
*/
|
||||
template <typename Signal, typename Handler>
|
||||
inline SignalInfo<Signal, Handler> signalInfo(typename QtPrivate::FunctionPointer<Signal>::Object *sender, Signal signal,
|
||||
const Handler &handler = Handler(), bool *correctSignalEmitted = nullptr)
|
||||
inline auto signalInfo(typename QtPrivate::FunctionPointer<Signal>::Object *sender, Signal signal, const Handler &handler = Handler(),
|
||||
bool *correctSignalEmitted = nullptr)
|
||||
{
|
||||
return SignalInfo<Signal, Handler>(sender, signal, handler, correctSignalEmitted);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new SignalInfo.
|
||||
*/
|
||||
template <typename Signal> inline auto signalInfo(typename QtPrivate::FunctionPointer<Signal>::Object *sender, Signal signal)
|
||||
{
|
||||
return SignalInfo<Signal, std::function<void(void)>>(sender, signal, std::function<void(void)>(), nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new SignalInfo.
|
||||
*/
|
||||
inline auto dummySignalInfo()
|
||||
{
|
||||
return SignalInfo<decltype(&QObject::destroyed), std::function<void(void)>>();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Connects the specified signal infos the \a loop via SignalInfo::connectToLoop().
|
||||
*/
|
||||
|
@ -275,13 +305,31 @@ inline QByteArray failedSignalNames(const SignalInfo &firstSignalInfo, const Sig
|
|||
* \arg signalInfos Specifies the signals to wait for.
|
||||
* \throws Fails if not all signals have been emitted in at least \a timeout milliseconds or when at least one of the
|
||||
* required connections can not be established.
|
||||
* \returns Returns true if all \a signalInfos have been omitted before the \a timeout exceeded.
|
||||
*/
|
||||
template <typename Action, typename... SignalInfos> void waitForSignals(Action action, int timeout, const SignalInfos &... signalInfos)
|
||||
template <typename Action, typename... SignalInfos> bool waitForSignals(Action action, int timeout, const SignalInfos &... signalInfos)
|
||||
{
|
||||
return waitForSignalsOrFail(action, timeout, dummySignalInfo(), signalInfos...);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Waits until the specified signals have been emitted when performing async operations triggered by \a action. Aborts when \a failure is emitted.
|
||||
* \arg action Specifies a method to trigger the action to run when waiting.
|
||||
* \arg timeout Specifies the max. time to wait. Set to zero to wait forever.
|
||||
* \arg failure Specifies the signal indicating an error occured.
|
||||
* \arg signalInfos Specifies the signals to wait for.
|
||||
* \throws Fails if not all signals have been emitted in at least \a timeout milliseconds or when at least one of the
|
||||
* required connections can not be established.
|
||||
* \returns Returns true if all \a signalInfos have been omitted before \a failure as been emitted or the \a timeout exceeded.
|
||||
*/
|
||||
template <typename Action, typename SignalInfo, typename... SignalInfos>
|
||||
bool waitForSignalsOrFail(Action action, int timeout, const SignalInfo &failure, const SignalInfos &... signalInfos)
|
||||
{
|
||||
// use loop for waiting
|
||||
QEventLoop loop;
|
||||
|
||||
// connect all signals to loop so loop is interrupted when one of the signals is emitted
|
||||
connectSignalInfosToLoop(&loop, failure);
|
||||
connectSignalInfosToLoop(&loop, signalInfos...);
|
||||
|
||||
// perform specified action
|
||||
|
@ -289,7 +337,10 @@ template <typename Action, typename... SignalInfos> void waitForSignals(Action a
|
|||
|
||||
// no reason to enter event loop when all signals have been emitted directly
|
||||
if (checkWhetherAllSignalsEmitted(signalInfos...)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (checkWhetherAllSignalsEmitted(failure)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// also connect and start a timer if a timeout has been specified
|
||||
|
@ -302,19 +353,26 @@ template <typename Action, typename... SignalInfos> void waitForSignals(Action a
|
|||
}
|
||||
|
||||
// exec event loop as long as the right signal has not been emitted yet and there is still time
|
||||
bool allSignalsEmitted = false;
|
||||
bool allSignalsEmitted = false, failureEmitted = false;
|
||||
do {
|
||||
loop.exec();
|
||||
} while (!(allSignalsEmitted = checkWhetherAllSignalsEmitted(signalInfos...)) && (!timeout || timer.isActive()));
|
||||
} while (!(failureEmitted = checkWhetherAllSignalsEmitted(failure)) && !(allSignalsEmitted = checkWhetherAllSignalsEmitted(signalInfos...))
|
||||
&& (!timeout || timer.isActive()));
|
||||
|
||||
// check whether a timeout occured
|
||||
// check whether a timeout occured
|
||||
const bool timeoutFailed(!allSignalsEmitted && timeout && !timer.isActive());
|
||||
#ifndef SYNCTHINGTESTHELPER_FOR_CLI
|
||||
if (!allSignalsEmitted && timeout && !timer.isActive()) {
|
||||
if (failureEmitted) {
|
||||
CPPUNIT_FAIL(
|
||||
argsToString("Signal(s) ", failedSignalNames(signalInfos...).data(), " has/have not emmitted before ", failure.signalName().data(), '.'));
|
||||
} else if (timeoutFailed) {
|
||||
CPPUNIT_FAIL(argsToString("Signal(s) ", failedSignalNames(signalInfos...).data(), " has/have not emmitted within at least ", timer.interval(),
|
||||
" ms.", timeoutFactor != 1.0 ? argsToString(" (original timeout: ", timeout, " ms)") : std::string()));
|
||||
}
|
||||
#endif
|
||||
return !failureEmitted && !timeoutFailed;
|
||||
}
|
||||
|
||||
} // namespace TestUtilities
|
||||
|
||||
#endif // SYNCTHINGTESTHELPER_H
|
||||
|
|
Loading…
Reference in New Issue