parent
633ed0eaab
commit
e4a382e4e8
|
@ -22,6 +22,7 @@ QT_FORWARD_DECLARE_CLASS(QJsonObject)
|
|||
QT_FORWARD_DECLARE_CLASS(QJsonArray)
|
||||
|
||||
class ConnectionTests;
|
||||
class MiscTests;
|
||||
|
||||
namespace Data {
|
||||
#undef Q_NAMESPACE
|
||||
|
@ -56,6 +57,7 @@ struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingLogEntry {
|
|||
|
||||
class LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingConnection : public QObject {
|
||||
friend ConnectionTests;
|
||||
friend MiscTests;
|
||||
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString syncthingUrl READ syncthingUrl WRITE setSyncthingUrl)
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
</device>
|
||||
<gui enabled="true" tls="false" debugging="false">
|
||||
<address>127.0.0.1:4001</address>
|
||||
<user>nobody</user>
|
||||
<password>$2a$12$35MnbsQgQNn1hzPYK/lWXOaP.U5D2TO0nuuQy2M4gsqJB4ff4q2RK</password>
|
||||
<apikey>syncthingconnectortest</apikey>
|
||||
<theme>default</theme>
|
||||
</gui>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "../syncthingconnection.h"
|
||||
#include "../syncthingconnectionsettings.h"
|
||||
|
||||
#include "../testhelper/helper.h"
|
||||
#include "../testhelper/syncthingtestinstance.h"
|
||||
|
@ -14,11 +15,40 @@
|
|||
|
||||
using namespace std;
|
||||
using namespace Data;
|
||||
using namespace ChronoUtilities;
|
||||
using namespace TestUtilities;
|
||||
using namespace TestUtilities::Literals;
|
||||
|
||||
using namespace CPPUNIT_NS;
|
||||
|
||||
class WaitForConnected : private function<void(void)>, public SignalInfo<decltype(&SyncthingConnection::statusChanged), function<void(void)>> {
|
||||
public:
|
||||
WaitForConnected(const SyncthingConnection &connection);
|
||||
operator bool() const;
|
||||
|
||||
private:
|
||||
const SyncthingConnection &m_connection;
|
||||
bool m_connectedAgain;
|
||||
};
|
||||
|
||||
WaitForConnected::WaitForConnected(const SyncthingConnection &connection)
|
||||
: function<void(void)>([this] {
|
||||
m_connectedAgain
|
||||
|= m_connection.statusText() == QStringLiteral("connected") || m_connection.statusText() == QStringLiteral("connected, scanning");
|
||||
})
|
||||
, SignalInfo<decltype(&SyncthingConnection::statusChanged), function<void(void)>>(
|
||||
&connection, &SyncthingConnection::statusChanged, (*static_cast<const function<void(void)> *>(this)), &m_connectedAgain)
|
||||
, m_connection(connection)
|
||||
, m_connectedAgain(false)
|
||||
{
|
||||
}
|
||||
|
||||
WaitForConnected::operator bool() const
|
||||
{
|
||||
(*static_cast<const function<void(void)> *>(this))(); // if the connection has already been connected it is ok, too
|
||||
return m_connectedAgain;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief The ConnectionTests class tests the SyncthingConnector.
|
||||
*/
|
||||
|
@ -34,14 +64,19 @@ public:
|
|||
|
||||
void testErrorCases();
|
||||
void testInitialConnection();
|
||||
void waitForAllDirsAndDevsReady();
|
||||
void testSendingError();
|
||||
void waitForAllDirsAndDevsReady(bool initialConfig = false);
|
||||
void checkDevices();
|
||||
void checkDirectories() const;
|
||||
void testReconnecting();
|
||||
void testResumingAllDevices();
|
||||
void testResumingDirectory();
|
||||
void testPausingDirectory();
|
||||
void testRequestingLog();
|
||||
void testRequestingQrCode();
|
||||
void testDisconnecting();
|
||||
void testConnectingWithSettings();
|
||||
void testRequestingRescan();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -57,6 +92,7 @@ private:
|
|||
|
||||
template <typename Handler> TemporaryConnection handleNewDevices(Handler handler, bool *ok);
|
||||
template <typename Handler> TemporaryConnection handleNewDirs(Handler handler, bool *ok);
|
||||
WaitForConnected waitForConnected() const;
|
||||
|
||||
SyncthingConnection m_connection;
|
||||
QString m_ownDevId;
|
||||
|
@ -88,7 +124,11 @@ void ConnectionTests::setUp()
|
|||
|
||||
// log configuration change
|
||||
QObject::connect(&m_connection, &SyncthingConnection::newConfig,
|
||||
[](const QJsonObject &config) { cerr << " - New config: " << QJsonDocument(config).toJson(QJsonDocument::Compact).data() << endl; });
|
||||
[](const QJsonObject &config) { cerr << " - New config: " << QJsonDocument(config).toJson(QJsonDocument::Indented).data() << endl; });
|
||||
|
||||
// log errors
|
||||
QObject::connect(&m_connection, &SyncthingConnection::error,
|
||||
[](const QString &message) { cerr << " - Connection error: " << message.toLocal8Bit().data() << endl; });
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -133,6 +173,11 @@ void (SyncthingConnection::*ConnectionTests::defaultDisconnect())(void)
|
|||
return static_cast<void (SyncthingConnection::*)(void)>(&SyncthingConnection::disconnect);
|
||||
}
|
||||
|
||||
WaitForConnected ConnectionTests::waitForConnected() const
|
||||
{
|
||||
return WaitForConnected(m_connection);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Helps handling newDevices() signal when waiting for device change.
|
||||
*/
|
||||
|
@ -168,14 +213,18 @@ void ConnectionTests::testConnection()
|
|||
{
|
||||
testErrorCases();
|
||||
testInitialConnection();
|
||||
waitForAllDirsAndDevsReady();
|
||||
checkDevices();
|
||||
checkDirectories();
|
||||
testSendingError();
|
||||
testReconnecting();
|
||||
testResumingAllDevices();
|
||||
testResumingDirectory();
|
||||
testPausingDirectory();
|
||||
testRequestingLog();
|
||||
testRequestingQrCode();
|
||||
testDisconnecting();
|
||||
testConnectingWithSettings();
|
||||
testRequestingRescan();
|
||||
}
|
||||
|
||||
void ConnectionTests::testErrorCases()
|
||||
|
@ -185,25 +234,35 @@ void ConnectionTests::testErrorCases()
|
|||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("Connection configuration is insufficient."), errorMessage);
|
||||
}));
|
||||
|
||||
cerr << "\n - Error handling in case of inavailability and wrong API key ..." << endl;
|
||||
cerr << "\n - Error handling in case of inavailability, wrong credentials and API key ..." << endl;
|
||||
m_connection.setApiKey(QByteArray("wrong API key"));
|
||||
bool syncthingAvailable = false;
|
||||
const function<void(const QString &errorMessage)> errorHandler = [this, &syncthingAvailable](const QString &errorMessage) {
|
||||
if (errorMessage == QStringLiteral("Unable to request Syncthing config: Connection refused")
|
||||
|| errorMessage == QStringLiteral("Unable to request Syncthing status: Connection refused")) {
|
||||
return; // Syncthing not ready yet
|
||||
}
|
||||
syncthingAvailable = true;
|
||||
if (errorMessage
|
||||
!= QStringLiteral("Unable to request Syncthing config: Error transferring ") % m_connection.syncthingUrl()
|
||||
% QStringLiteral("/rest/system/config - server replied: Forbidden")
|
||||
&& errorMessage
|
||||
!= QStringLiteral("Unable to request Syncthing status: Error transferring ") % m_connection.syncthingUrl()
|
||||
% QStringLiteral("/rest/system/status - server replied: Forbidden")) {
|
||||
CPPUNIT_FAIL(argsToString("wrong error message in case of wrong API key: ", errorMessage.toLocal8Bit().data()));
|
||||
}
|
||||
};
|
||||
while (!syncthingAvailable) {
|
||||
bool syncthingAvailable = false, authError = false, apiKeyError = false;
|
||||
const function<void(const QString &errorMessage)> errorHandler
|
||||
= [this, &syncthingAvailable, &authError, &apiKeyError](const QString &errorMessage) {
|
||||
if (errorMessage == QStringLiteral("Unable to request Syncthing config: Connection refused")
|
||||
|| errorMessage == QStringLiteral("Unable to request Syncthing status: Connection refused")) {
|
||||
// Syncthing not ready yet, wait 100 ms till next connection attempt
|
||||
wait(100);
|
||||
return;
|
||||
}
|
||||
syncthingAvailable = true;
|
||||
if (errorMessage == QStringLiteral("Unable to request Syncthing status: Host requires authentication")
|
||||
|| errorMessage == QStringLiteral("Unable to request Syncthing config: Host requires authentication")) {
|
||||
m_connection.setCredentials(QStringLiteral("nobody"), QStringLiteral("supersecret"));
|
||||
authError = true;
|
||||
return;
|
||||
}
|
||||
if ((errorMessage.startsWith(QStringLiteral("Unable to request Syncthing status: Error transferring "))
|
||||
&& errorMessage.endsWith(QStringLiteral("/rest/system/status - server replied: Forbidden")))
|
||||
|| (errorMessage.startsWith(QStringLiteral("Unable to request Syncthing config: Error transferring "))
|
||||
&& errorMessage.endsWith(QStringLiteral("/rest/system/config - server replied: Forbidden")))) {
|
||||
m_connection.setApiKey(apiKey().toUtf8());
|
||||
apiKeyError = true;
|
||||
return;
|
||||
}
|
||||
CPPUNIT_FAIL(argsToString("wrong error message: ", errorMessage.toLocal8Bit().data()));
|
||||
};
|
||||
while (!syncthingAvailable || !authError || !apiKeyError) {
|
||||
waitForConnection(defaultConnect(), 5000, connectionSignal(&SyncthingConnection::error, errorHandler));
|
||||
}
|
||||
}
|
||||
|
@ -211,42 +270,64 @@ void ConnectionTests::testErrorCases()
|
|||
void ConnectionTests::testInitialConnection()
|
||||
{
|
||||
cerr << "\n - Connecting initially ..." << endl;
|
||||
m_connection.setApiKey(apiKey().toUtf8());
|
||||
waitForConnection(defaultConnect(), 5000, connectionSignal(&SyncthingConnection::statusChanged));
|
||||
waitForAllDirsAndDevsReady(true);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
||||
"connected and paused (one dev is initially paused)", QStringLiteral("connected, paused"), m_connection.statusText());
|
||||
CPPUNIT_ASSERT_MESSAGE("no dirs out-of-sync", !m_connection.hasOutOfSyncDirs());
|
||||
}
|
||||
|
||||
void ConnectionTests::waitForAllDirsAndDevsReady()
|
||||
void ConnectionTests::testSendingError()
|
||||
{
|
||||
bool newNotificationEmitted = false;
|
||||
const DateTime sentTime(DateTime::now());
|
||||
const QString sentMessage(QStringLiteral("test notification"));
|
||||
const function<void(ChronoUtilities::DateTime receivedTime, const QString &receivedMessage)> newNotificationHandler
|
||||
= [&](ChronoUtilities::DateTime receivedTime, const QString &receivedMessage) {
|
||||
newNotificationEmitted |= receivedTime == sentTime && receivedMessage == sentMessage;
|
||||
};
|
||||
waitForSignals([this, sentTime, &sentMessage] { m_connection.emitNotification(sentTime, sentMessage); }, 500,
|
||||
connectionSignal(&SyncthingConnection::newNotification, newNotificationHandler, &newNotificationEmitted));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ensures the connection is established and waits till all dirs and devs are ready.
|
||||
* \param initialConfig Whether to check for initial config (at least one dir and one dev is paused).
|
||||
*/
|
||||
void ConnectionTests::waitForAllDirsAndDevsReady(const bool initialConfig)
|
||||
{
|
||||
bool allDirsReady, allDevsReady;
|
||||
const function<void()> checkAllDirsReady([this, &allDirsReady] {
|
||||
bool oneDirPaused = false, oneDevPaused = false;
|
||||
bool isConnected = m_connection.isConnected();
|
||||
const function<void()> checkAllDirsReady([this, &allDirsReady, &initialConfig, &oneDirPaused] {
|
||||
for (const SyncthingDir &dir : m_connection.dirInfo()) {
|
||||
if (dir.status == SyncthingDirStatus::Unknown) {
|
||||
allDirsReady = false;
|
||||
return;
|
||||
}
|
||||
oneDirPaused |= dir.paused;
|
||||
}
|
||||
allDirsReady = true;
|
||||
allDirsReady = !initialConfig || oneDirPaused;
|
||||
});
|
||||
const function<void()> checkAllDevsReady([this, &allDevsReady] {
|
||||
const function<void()> checkAllDevsReady([this, &allDevsReady, &initialConfig, &oneDevPaused] {
|
||||
for (const SyncthingDev &dev : m_connection.devInfo()) {
|
||||
if (dev.status == SyncthingDevStatus::Unknown) {
|
||||
allDevsReady = false;
|
||||
return;
|
||||
}
|
||||
oneDevPaused |= dev.paused;
|
||||
}
|
||||
allDevsReady = true;
|
||||
allDevsReady = !initialConfig || oneDevPaused;
|
||||
});
|
||||
const function<void(SyncthingStatus)> checkStatus([this, &isConnected](SyncthingStatus) { isConnected = m_connection.isConnected(); });
|
||||
checkAllDirsReady();
|
||||
checkAllDevsReady();
|
||||
if (allDirsReady && allDevsReady) {
|
||||
return;
|
||||
}
|
||||
waitForSignals(noop, 1000, connectionSignal(&SyncthingConnection::dirStatusChanged, checkAllDirsReady, &allDirsReady),
|
||||
waitForSignals(bind(defaultConnect(), &m_connection), 5000, connectionSignal(&SyncthingConnection::statusChanged, checkStatus, &isConnected),
|
||||
connectionSignal(&SyncthingConnection::dirStatusChanged, checkAllDirsReady, &allDirsReady),
|
||||
connectionSignal(&SyncthingConnection::newDirs, checkAllDirsReady, &allDirsReady),
|
||||
connectionSignal(&SyncthingConnection::dirStatusChanged, checkAllDevsReady, &allDevsReady),
|
||||
connectionSignal(&SyncthingConnection::devStatusChanged, checkAllDevsReady, &allDevsReady),
|
||||
connectionSignal(&SyncthingConnection::newDevices, checkAllDevsReady, &allDevsReady));
|
||||
}
|
||||
|
||||
|
@ -261,21 +342,36 @@ void ConnectionTests::checkDevices()
|
|||
m_ownDevId = dev.id;
|
||||
}
|
||||
}
|
||||
const SyncthingDev *dev1 = nullptr, *dev2 = nullptr;
|
||||
int index = 0, dev1Index, dev2Index;
|
||||
for (const SyncthingDev &dev : devInfo) {
|
||||
CPPUNIT_ASSERT(!dev.isConnected());
|
||||
if (dev.id == QStringLiteral("MMGUI6U-WUEZQCP-XZZ6VYB-LCT4TVC-ER2HAVX-QYT6X7D-S6ZSG2B-323KLQ7")) {
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("paused device", QStringLiteral("paused"), dev.statusString());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("name", QStringLiteral("Test dev 2"), dev.name);
|
||||
CPPUNIT_ASSERT_MESSAGE("no introducer", !dev.introducer);
|
||||
CPPUNIT_ASSERT_EQUAL(1, dev.addresses.size());
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("tcp://192.168.2.2:22000"), dev.addresses.front());
|
||||
dev2 = &dev;
|
||||
dev2Index = index;
|
||||
} else if (dev.id == QStringLiteral("6EIS2PN-J2IHWGS-AXS3YUL-HC5FT3K-77ZXTLL-AKQLJ4C-7SWVPUS-AZW4RQ4")) {
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("disconnected device", QStringLiteral("disconnected"), dev.statusString());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("name", QStringLiteral("Test dev 1"), dev.name);
|
||||
CPPUNIT_ASSERT_MESSAGE("introducer", dev.introducer);
|
||||
CPPUNIT_ASSERT_EQUAL(1, dev.addresses.size());
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("dynamic"), dev.addresses.front());
|
||||
dev1 = &dev;
|
||||
dev1Index = index;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT(dev1 && dev2);
|
||||
CPPUNIT_ASSERT(dev1 == m_connection.findDevInfo(QStringLiteral("6EIS2PN-J2IHWGS-AXS3YUL-HC5FT3K-77ZXTLL-AKQLJ4C-7SWVPUS-AZW4RQ4"), index));
|
||||
CPPUNIT_ASSERT_EQUAL(dev1Index, index);
|
||||
CPPUNIT_ASSERT(dev2 == m_connection.findDevInfoByName(QStringLiteral("Test dev 2"), index));
|
||||
CPPUNIT_ASSERT_EQUAL(dev2Index, index);
|
||||
CPPUNIT_ASSERT(!m_connection.findDevInfoByName(QStringLiteral("does not exist"), index));
|
||||
}
|
||||
|
||||
void ConnectionTests::checkDirectories() const
|
||||
|
@ -287,6 +383,7 @@ void ConnectionTests::checkDirectories() const
|
|||
CPPUNIT_ASSERT_EQUAL(QStringLiteral(""), dir1.label);
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("test1"), dir1.displayName());
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("/tmp/some/path/1/"), dir1.path);
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir1.statusString());
|
||||
CPPUNIT_ASSERT(!dir1.readOnly);
|
||||
CPPUNIT_ASSERT(!dir1.paused);
|
||||
CPPUNIT_ASSERT_EQUAL(dir1.devices.toSet(), QSet<QString>({ QStringLiteral("MMGUI6U-WUEZQCP-XZZ6VYB-LCT4TVC-ER2HAVX-QYT6X7D-S6ZSG2B-323KLQ7"),
|
||||
|
@ -296,6 +393,8 @@ void ConnectionTests::checkDirectories() const
|
|||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("Test dir 2"), dir2.label);
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("Test dir 2"), dir2.displayName());
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("/tmp/some/path/2/"), dir2.path);
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("/tmp/some/path/2"), dir2.pathWithoutTrailingSlash().toString());
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("paused"), dir2.statusString());
|
||||
CPPUNIT_ASSERT(!dir2.readOnly);
|
||||
CPPUNIT_ASSERT(dir2.paused);
|
||||
CPPUNIT_ASSERT_EQUAL(
|
||||
|
@ -306,12 +405,7 @@ void ConnectionTests::testReconnecting()
|
|||
{
|
||||
cerr << "\n - Reconnecting ..." << endl;
|
||||
waitForConnection(defaultReconnect(), 1000, connectionSignal(&SyncthingConnection::statusChanged));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("reconnecting", QStringLiteral("reconnecting"), m_connection.statusText());
|
||||
waitForSignals(noop, 1000, connectionSignal(&SyncthingConnection::statusChanged));
|
||||
if (m_connection.isConnected() && m_connection.status() != SyncthingStatus::Paused) {
|
||||
// FIXME: Maybe it takes one further update to recognize paused dev?
|
||||
waitForSignals(noop, 1000, connectionSignal(&SyncthingConnection::statusChanged));
|
||||
}
|
||||
waitForAllDirsAndDevsReady(true);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("connected again", QStringLiteral("connected, paused"), m_connection.statusText());
|
||||
}
|
||||
|
||||
|
@ -327,16 +421,16 @@ void ConnectionTests::testResumingAllDevices()
|
|||
const function<void(const QStringList &)> devResumedTriggeredHandler
|
||||
= [this](const QStringList &devIds) { CPPUNIT_ASSERT_EQUAL(m_connection.deviceIds(), devIds); };
|
||||
const auto newDevsConnection = handleNewDevices(devResumedHandler, &devResumed);
|
||||
waitForConnection(&SyncthingConnection::resumeAllDevs, 3000,
|
||||
waitForConnection(&SyncthingConnection::resumeAllDevs, 7500, waitForConnected(),
|
||||
connectionSignal(&SyncthingConnection::devStatusChanged, devResumedHandler, &devResumed),
|
||||
connectionSignal(&SyncthingConnection::deviceResumeTriggered, devResumedTriggeredHandler));
|
||||
CPPUNIT_ASSERT(devResumed);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("not paused anymore", QStringLiteral("connected"), m_connection.statusText());
|
||||
for (const QJsonValue &devValue : m_connection.m_rawConfig.value(QStringLiteral("devices")).toArray()) {
|
||||
const QJsonObject &devObj(devValue.toObject());
|
||||
CPPUNIT_ASSERT(!devObj.isEmpty());
|
||||
CPPUNIT_ASSERT_MESSAGE("raw config updated accordingly", !devObj.value(QStringLiteral("paused")).toBool(true));
|
||||
}
|
||||
CPPUNIT_ASSERT_MESSAGE("resuming all devs should not cause another request again", !m_connection.resumeAllDevs());
|
||||
}
|
||||
|
||||
void ConnectionTests::testResumingDirectory()
|
||||
|
@ -348,12 +442,15 @@ void ConnectionTests::testResumingDirectory()
|
|||
dirResumed = true;
|
||||
}
|
||||
};
|
||||
const function<void(const QStringList &)> dirResumedTriggeredHandler
|
||||
= [this](const QStringList &devIds) { CPPUNIT_ASSERT_EQUAL(m_connection.directoryIds(), devIds); };
|
||||
const auto newDirsConnection = handleNewDirs(dirResumedHandler, &dirResumed);
|
||||
waitForConnection(
|
||||
&SyncthingConnection::resumeAllDirs, 3000, connectionSignal(&SyncthingConnection::dirStatusChanged, dirResumedHandler, &dirResumed));
|
||||
waitForConnection(&SyncthingConnection::resumeAllDirs, 7500, waitForConnected(),
|
||||
connectionSignal(&SyncthingConnection::dirStatusChanged, dirResumedHandler, &dirResumed),
|
||||
connectionSignal(&SyncthingConnection::directoryResumeTriggered, dirResumedTriggeredHandler));
|
||||
CPPUNIT_ASSERT(dirResumed);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("still 2 dirs present", 2_st, m_connection.dirInfo().size());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("still not paused anymore", QStringLiteral("connected"), m_connection.statusText());
|
||||
CPPUNIT_ASSERT_MESSAGE("resuming all dirs should not cause another request again", !m_connection.resumeAllDirs());
|
||||
}
|
||||
|
||||
void ConnectionTests::testPausingDirectory()
|
||||
|
@ -365,12 +462,66 @@ void ConnectionTests::testPausingDirectory()
|
|||
dirPaused = true;
|
||||
}
|
||||
};
|
||||
const QStringList ids({ QStringLiteral("test1") });
|
||||
const function<void(const QStringList &)> dirPausedTriggeredHandler
|
||||
= [this, &ids](const QStringList &devIds) { CPPUNIT_ASSERT_EQUAL(ids, devIds); };
|
||||
const auto newDirsConnection = handleNewDirs(dirPausedHandler, &dirPaused);
|
||||
waitForSignals(bind(&SyncthingConnection::pauseDirectories, &m_connection, QStringList({ QStringLiteral("test1") })), 3000,
|
||||
connectionSignal(&SyncthingConnection::dirStatusChanged, dirPausedHandler, &dirPaused));
|
||||
waitForSignals(bind(&SyncthingConnection::pauseDirectories, &m_connection, ids), 7500, waitForConnected(),
|
||||
connectionSignal(&SyncthingConnection::dirStatusChanged, dirPausedHandler, &dirPaused),
|
||||
connectionSignal(&SyncthingConnection::directoryPauseTriggered, dirPausedTriggeredHandler));
|
||||
CPPUNIT_ASSERT(dirPaused);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("still 2 dirs present", 2_st, m_connection.dirInfo().size());
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("still not paused anymore", QStringLiteral("connected"), m_connection.statusText());
|
||||
CPPUNIT_ASSERT_MESSAGE("pausing should not cause another request again", !m_connection.pauseDirectories(ids));
|
||||
}
|
||||
|
||||
void ConnectionTests::testRequestingLog()
|
||||
{
|
||||
cerr << "\n - Requesting log ..." << endl;
|
||||
|
||||
// timeout after 1 second
|
||||
QTimer timeout;
|
||||
timeout.setSingleShot(true);
|
||||
timeout.setInterval(1000);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&timeout, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||||
|
||||
bool callbackOk = false;
|
||||
const auto request = m_connection.requestLog([&callbackOk, &loop](const std::vector<SyncthingLogEntry> &logEntries) {
|
||||
callbackOk = true;
|
||||
CPPUNIT_ASSERT(!logEntries.empty());
|
||||
CPPUNIT_ASSERT(!logEntries[0].when.isEmpty());
|
||||
CPPUNIT_ASSERT(!logEntries[0].message.isEmpty());
|
||||
loop.quit();
|
||||
});
|
||||
|
||||
timeout.start();
|
||||
loop.exec();
|
||||
QObject::disconnect(request); // ensure callback is not called after return (in error case)
|
||||
CPPUNIT_ASSERT_MESSAGE("log entries returned before timeout", callbackOk);
|
||||
}
|
||||
|
||||
void ConnectionTests::testRequestingQrCode()
|
||||
{
|
||||
cerr << "\n - Requesting QR-Code for own device ID ..." << endl;
|
||||
|
||||
// timeout after 2 seconds
|
||||
QTimer timeout;
|
||||
timeout.setSingleShot(true);
|
||||
timeout.setInterval(2000);
|
||||
QEventLoop loop;
|
||||
QObject::connect(&timeout, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||||
|
||||
bool callbackOk = false;
|
||||
const auto request = m_connection.requestQrCode(m_ownDevId, [this, &callbackOk, &loop](const QByteArray &data) {
|
||||
callbackOk = true;
|
||||
CPPUNIT_ASSERT(!data.isEmpty());
|
||||
loop.quit();
|
||||
});
|
||||
|
||||
timeout.start();
|
||||
loop.exec();
|
||||
QObject::disconnect(request); // ensure callback is not called after return (in error case)
|
||||
CPPUNIT_ASSERT_MESSAGE("QR code returned before timeout", callbackOk);
|
||||
}
|
||||
|
||||
void ConnectionTests::testDisconnecting()
|
||||
|
@ -379,3 +530,38 @@ void ConnectionTests::testDisconnecting()
|
|||
waitForConnection(defaultDisconnect(), 1000, connectionSignal(&SyncthingConnection::statusChanged));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("disconnected", QStringLiteral("disconnected"), m_connection.statusText());
|
||||
}
|
||||
|
||||
void ConnectionTests::testConnectingWithSettings()
|
||||
{
|
||||
cerr << "\n - Connecting with settings ..." << endl;
|
||||
SyncthingConnectionSettings settings;
|
||||
settings.syncthingUrl = m_connection.syncthingUrl();
|
||||
settings.apiKey = m_connection.apiKey();
|
||||
settings.userName = m_connection.user();
|
||||
settings.password = m_connection.password();
|
||||
|
||||
bool isConnected;
|
||||
const function<void(SyncthingStatus)> checkStatus([this, &isConnected](SyncthingStatus) { isConnected = m_connection.isConnected(); });
|
||||
waitForSignals(
|
||||
bind(static_cast<void (SyncthingConnection::*)(SyncthingConnectionSettings &)>(&SyncthingConnection::connect), &m_connection, ref(settings)),
|
||||
5000, connectionSignal(&SyncthingConnection::statusChanged, checkStatus, &isConnected));
|
||||
}
|
||||
|
||||
void ConnectionTests::testRequestingRescan()
|
||||
{
|
||||
cerr << "\n - Requesting rescan ..." << endl;
|
||||
|
||||
bool rescanTriggered = false;
|
||||
function<void(const QString &)> rescanTriggeredHandler = [this, &rescanTriggered](const QString &dir) {
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("test2"), dir);
|
||||
rescanTriggered = true;
|
||||
};
|
||||
bool errorOccured = false;
|
||||
function<void(const QString &)> errorHandler = [this, &errorOccured](const QString &message) {
|
||||
errorOccured |= message.startsWith(QStringLiteral("Unable to request rescan: Error transferring"))
|
||||
&& message.endsWith(QStringLiteral("/rest/db/scan?folder=test1 - server replied: Internal Server Error"));
|
||||
};
|
||||
waitForSignals(bind(&SyncthingConnection::rescanAllDirs, &m_connection), 5000,
|
||||
connectionSignal(&SyncthingConnection::rescanTriggered, rescanTriggeredHandler, &rescanTriggered),
|
||||
connectionSignal(&SyncthingConnection::error, errorHandler, &errorOccured));
|
||||
}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
#include "../syncthingconfig.h"
|
||||
#include "../syncthingconnection.h"
|
||||
#include "../syncthingconnectionsettings.h"
|
||||
#include "../syncthingservice.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#include "../testhelper/helper.h"
|
||||
|
||||
#include <c++utilities/chrono/datetime.h>
|
||||
#include <c++utilities/chrono/format.h>
|
||||
#include <c++utilities/chrono/timespan.h>
|
||||
#include <c++utilities/tests/testutils.h>
|
||||
|
||||
#include "../testhelper/helper.h"
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
|
||||
using namespace std;
|
||||
|
@ -25,6 +30,9 @@ class MiscTests : public TestFixture {
|
|||
CPPUNIT_TEST_SUITE(MiscTests);
|
||||
CPPUNIT_TEST(testParsingConfig);
|
||||
CPPUNIT_TEST(testUtils);
|
||||
CPPUNIT_TEST(testService);
|
||||
CPPUNIT_TEST(testConnectionSettingsAndLoadingSelfSignedCert);
|
||||
CPPUNIT_TEST(testSyncthingDir);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
|
@ -32,6 +40,9 @@ public:
|
|||
|
||||
void testParsingConfig();
|
||||
void testUtils();
|
||||
void testService();
|
||||
void testConnectionSettingsAndLoadingSelfSignedCert();
|
||||
void testSyncthingDir();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -67,15 +78,25 @@ void MiscTests::tearDown()
|
|||
void MiscTests::testParsingConfig()
|
||||
{
|
||||
SyncthingConfig config;
|
||||
config.restore(QString::fromLocal8Bit(testFilePath("testconfig/config.xml").data()));
|
||||
CPPUNIT_ASSERT(!config.restore(QStringLiteral("non-existant-file")));
|
||||
CPPUNIT_ASSERT(config.restore(QString::fromLocal8Bit(testFilePath("testconfig/config.xml").data())));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("address", QStringLiteral("127.0.0.1:4001"), config.guiAddress);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("API key", QStringLiteral("syncthingconnectortest"), config.guiApiKey);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("user", QStringLiteral("nobody"), config.guiUser);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("password", QStringLiteral("$2a$12$35MnbsQgQNn1hzPYK/lWXOaP.U5D2TO0nuuQy2M4gsqJB4ff4q2RK"), config.guiPasswordHash);
|
||||
CPPUNIT_ASSERT_MESSAGE("TLS", !config.guiEnforcesSecureConnection);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("url", QStringLiteral("http://127.0.0.1:4001"), config.syncthingUrl());
|
||||
config.guiEnforcesSecureConnection = true;
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("url", QStringLiteral("https://127.0.0.1:4001"), config.syncthingUrl());
|
||||
const QString configFile(SyncthingConfig::locateConfigFile());
|
||||
CPPUNIT_ASSERT(configFile.isEmpty() || QFile::exists(configFile));
|
||||
const QString httpsCert(SyncthingConfig::locateHttpsCertificate());
|
||||
CPPUNIT_ASSERT(httpsCert.isEmpty() || QFile::exists(httpsCert));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Tests utils.
|
||||
*/
|
||||
void MiscTests::testUtils()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("right now"), agoString(DateTime::now()));
|
||||
|
@ -85,3 +106,101 @@ void MiscTests::testUtils()
|
|||
CPPUNIT_ASSERT(isLocal(QUrl(QStringLiteral("http://localhost/"))));
|
||||
CPPUNIT_ASSERT(!isLocal(QUrl(QStringLiteral("http://157.3.52.34"))));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Tests SyncthingService class, but error case with non-existant service so far.
|
||||
*/
|
||||
void MiscTests::testService()
|
||||
{
|
||||
SyncthingService service;
|
||||
service.isSystemdAvailable();
|
||||
service.setUnitName(QStringLiteral("non-existant.service"));
|
||||
CPPUNIT_ASSERT(!service.isUnitAvailable());
|
||||
CPPUNIT_ASSERT_EQUAL(QString(), service.description());
|
||||
CPPUNIT_ASSERT(!service.isRunning());
|
||||
CPPUNIT_ASSERT(!service.isEnabled());
|
||||
service.toggleRunning();
|
||||
service.setEnabled(true);
|
||||
}
|
||||
|
||||
void MiscTests::testConnectionSettingsAndLoadingSelfSignedCert()
|
||||
{
|
||||
SyncthingConnectionSettings settings;
|
||||
settings.syncthingUrl = QStringLiteral("http://localhost:8080");
|
||||
settings.apiKey = QByteArray("foo");
|
||||
settings.httpsCertPath = SyncthingConfig::locateHttpsCertificate();
|
||||
if (settings.loadHttpsCert()) {
|
||||
CPPUNIT_ASSERT_EQUAL(4, settings.expectedSslErrors.size());
|
||||
} else {
|
||||
CPPUNIT_ASSERT_EQUAL(0, settings.expectedSslErrors.size());
|
||||
}
|
||||
SyncthingConnection connection;
|
||||
CPPUNIT_ASSERT(connection.applySettings(settings));
|
||||
CPPUNIT_ASSERT(!connection.loadSelfSignedCertificate());
|
||||
settings.syncthingUrl = QStringLiteral("https://localhost:8080");
|
||||
CPPUNIT_ASSERT(connection.applySettings(settings));
|
||||
connection.m_configDir = QStringLiteral("some-non/existent-dir");
|
||||
bool errorOccured = false;
|
||||
const function<void(const QString &)> errorHandler
|
||||
= [&errorOccured](const QString &message) { errorOccured |= message == QStringLiteral("Unable to load certificate used by Syncthing."); };
|
||||
waitForSignals(bind(&SyncthingConnection::loadSelfSignedCertificate, &connection), 1,
|
||||
signalInfo(&connection, &SyncthingConnection::error, errorHandler, &errorOccured));
|
||||
settings.expectedSslErrors.clear();
|
||||
CPPUNIT_ASSERT(!connection.applySettings(settings));
|
||||
}
|
||||
|
||||
void MiscTests::testSyncthingDir()
|
||||
{
|
||||
SyncthingDir dir;
|
||||
dir.devices << QStringLiteral("dev1") << QStringLiteral("dev2");
|
||||
|
||||
DateTime updateTime(DateTime::fromDate(2005, 2, 3));
|
||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Unshared, updateTime));
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("unshared"), dir.statusString());
|
||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastStatusUpdate);
|
||||
|
||||
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Scanning, DateTime::fromDate(2003, 6, 7)));
|
||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastStatusUpdate);
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("unshared"), dir.statusString());
|
||||
|
||||
const DateTime lastScanTime(DateTime::now());
|
||||
updateTime += TimeSpan::fromSeconds(5);
|
||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Scanning, updateTime));
|
||||
CPPUNIT_ASSERT(dir.lastScanTime.isNull());
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("scanning"), dir.statusString());
|
||||
|
||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromSeconds(2)));
|
||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastStatusUpdate);
|
||||
CPPUNIT_ASSERT(dir.lastScanTime >= lastScanTime);
|
||||
|
||||
dir.errors.emplace_back(QStringLiteral("message"), QStringLiteral("path"));
|
||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("out of sync"), dir.statusString());
|
||||
|
||||
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("syncing"), updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
|
||||
dir.errors.clear();
|
||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("error"), updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("out of sync"), dir.statusString());
|
||||
|
||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("wrong status"), updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong status treated as idle", QStringLiteral("idle"), dir.statusString());
|
||||
|
||||
CPPUNIT_ASSERT_MESSAGE("older status discarded", !dir.assignStatus(QStringLiteral("scanning"), updateTime - TimeSpan::fromSeconds(1)));
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir.statusString());
|
||||
|
||||
dir.errors.emplace_back(QStringLiteral("message"), QStringLiteral("path"));
|
||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("idle"), updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("out of sync"), dir.statusString());
|
||||
|
||||
dir.errors.clear();
|
||||
dir.devices.removeLast();
|
||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("idle"), updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("dir considered unshared when only one dev present", QStringLiteral("unshared"), dir.statusString());
|
||||
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("dir considered unshared when only one dev present", QStringLiteral("unshared"), dir.statusString());
|
||||
|
||||
updateTime += TimeSpan::fromMinutes(1.5);
|
||||
CPPUNIT_ASSERT_MESSAGE("same status again not considered an update", !dir.assignStatus(QStringLiteral("idle"), updateTime));
|
||||
}
|
||||
|
|
|
@ -70,6 +70,13 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
TemporaryConnection(const TemporaryConnection &other) = delete;
|
||||
|
||||
TemporaryConnection(TemporaryConnection &&other)
|
||||
: m_connection(std::move(other.m_connection))
|
||||
{
|
||||
}
|
||||
|
||||
~TemporaryConnection()
|
||||
{
|
||||
QObject::disconnect(m_connection);
|
||||
|
@ -95,23 +102,23 @@ public:
|
|||
* \param correctSignalEmitted Specifies whether the correct signal has been emitted. Should be set in \a handler to indicate that the emitted signal is actually the one
|
||||
* the test is waiting for (and not just one which has been emitted as side-effect).
|
||||
*/
|
||||
SignalInfo(
|
||||
typename QtPrivate::FunctionPointer<Signal>::Object *sender, Signal signal, const Handler &handler, bool *correctSignalEmitted = nullptr)
|
||||
: sender(sender)
|
||||
, signal(signal)
|
||||
, correctSignalEmitted(correctSignalEmitted)
|
||||
, signalEmitted(false)
|
||||
SignalInfo(const typename QtPrivate::FunctionPointer<Signal>::Object *sender, Signal signal, const Handler &handler,
|
||||
bool *correctSignalEmitted = nullptr)
|
||||
: m_sender(sender)
|
||||
, m_signal(signal)
|
||||
, m_correctSignalEmitted(correctSignalEmitted)
|
||||
, m_signalEmitted(false)
|
||||
{
|
||||
// register handler if specified
|
||||
if (handler) {
|
||||
handlerConnection = QObject::connect(sender, signal, sender, handler, Qt::DirectConnection);
|
||||
if (!handlerConnection) {
|
||||
m_handlerConnection = QObject::connect(sender, signal, sender, handler, Qt::DirectConnection);
|
||||
if (!m_handlerConnection) {
|
||||
CPPUNIT_FAIL(argsToString("Unable to connect signal ", signalName().data(), " to handler"));
|
||||
}
|
||||
}
|
||||
// register own handler to detect whether signal has been emitted
|
||||
emittedConnection = QObject::connect(sender, signal, sender, [this] { signalEmitted = true; }, Qt::DirectConnection);
|
||||
if (!emittedConnection) {
|
||||
m_emittedConnection = QObject::connect(sender, signal, sender, [this] { m_signalEmitted = true; }, Qt::DirectConnection);
|
||||
if (!m_emittedConnection) {
|
||||
CPPUNIT_FAIL(argsToString("Unable to connect signal ", signalName().data(), " to check for signal emmitation"));
|
||||
}
|
||||
}
|
||||
|
@ -119,15 +126,15 @@ public:
|
|||
SignalInfo(const SignalInfo &other) = delete;
|
||||
|
||||
SignalInfo(SignalInfo &&other)
|
||||
: sender(other.sender)
|
||||
, signal(other.signal)
|
||||
, handlerConnection(other.handlerConnection)
|
||||
, emittedConnection(other.emittedConnection)
|
||||
, loopConnection(other.loopConnection)
|
||||
, correctSignalEmitted(other.correctSignalEmitted)
|
||||
, signalEmitted(other.signalEmitted)
|
||||
: m_sender(other.m_sender)
|
||||
, m_signal(other.m_signal)
|
||||
, m_handlerConnection(other.m_handlerConnection)
|
||||
, m_emittedConnection(other.m_emittedConnection)
|
||||
, m_loopConnection(other.m_loopConnection)
|
||||
, m_correctSignalEmitted(other.m_correctSignalEmitted)
|
||||
, m_signalEmitted(other.m_signalEmitted)
|
||||
{
|
||||
other.handlerConnection = other.emittedConnection = other.loopConnection = QMetaObject::Connection();
|
||||
other.m_handlerConnection = other.m_emittedConnection = other.m_loopConnection = QMetaObject::Connection();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -135,9 +142,9 @@ public:
|
|||
*/
|
||||
~SignalInfo()
|
||||
{
|
||||
QObject::disconnect(handlerConnection);
|
||||
QObject::disconnect(emittedConnection);
|
||||
QObject::disconnect(loopConnection);
|
||||
QObject::disconnect(m_handlerConnection);
|
||||
QObject::disconnect(m_emittedConnection);
|
||||
QObject::disconnect(m_loopConnection);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -145,7 +152,7 @@ public:
|
|||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return (correctSignalEmitted && *correctSignalEmitted) || (!correctSignalEmitted && signalEmitted);
|
||||
return (m_correctSignalEmitted && *m_correctSignalEmitted) || (!m_correctSignalEmitted && m_signalEmitted);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -153,7 +160,7 @@ public:
|
|||
*/
|
||||
QByteArray signalName() const
|
||||
{
|
||||
return QMetaMethod::fromSignal(signal).name();
|
||||
return QMetaMethod::fromSignal(m_signal).name();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -162,21 +169,21 @@ public:
|
|||
*/
|
||||
void connectToLoop(QEventLoop *loop) const
|
||||
{
|
||||
QObject::disconnect(loopConnection);
|
||||
loopConnection = QObject::connect(sender, signal, loop, &QEventLoop::quit, Qt::DirectConnection);
|
||||
if (!loopConnection) {
|
||||
QObject::disconnect(m_loopConnection);
|
||||
m_loopConnection = QObject::connect(m_sender, m_signal, loop, &QEventLoop::quit, Qt::DirectConnection);
|
||||
if (!m_loopConnection) {
|
||||
CPPUNIT_FAIL(argsToString("Unable to connect signal ", signalName().data(), " for waiting"));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typename QtPrivate::FunctionPointer<Signal>::Object *sender;
|
||||
Signal signal;
|
||||
QMetaObject::Connection handlerConnection;
|
||||
QMetaObject::Connection emittedConnection;
|
||||
mutable QMetaObject::Connection loopConnection;
|
||||
bool *correctSignalEmitted = nullptr;
|
||||
bool signalEmitted;
|
||||
const typename QtPrivate::FunctionPointer<Signal>::Object *m_sender;
|
||||
Signal m_signal;
|
||||
QMetaObject::Connection m_handlerConnection;
|
||||
QMetaObject::Connection m_emittedConnection;
|
||||
mutable QMetaObject::Connection m_loopConnection;
|
||||
bool *m_correctSignalEmitted = nullptr;
|
||||
bool m_signalEmitted;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
|
@ -41,6 +41,11 @@ void SyncthingTestInstance::start()
|
|||
}
|
||||
}
|
||||
|
||||
// ensure dirs exist
|
||||
const QDir parentDir(QStringLiteral("/tmp/some/path"));
|
||||
parentDir.mkpath(QStringLiteral("1"));
|
||||
parentDir.mkpath(QStringLiteral("2"));
|
||||
|
||||
// determine st path
|
||||
const QByteArray syncthingPathFromEnv(qgetenv("SYNCTHING_PATH"));
|
||||
const QString syncthingPath(syncthingPathFromEnv.isEmpty() ? QStringLiteral("syncthing") : QString::fromLocal8Bit(syncthingPathFromEnv));
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "./global.h"
|
||||
#include "./helper.h"
|
||||
|
||||
#include "../syncthingconnector/syncthingprocess.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QProcess>
|
||||
|
||||
|
@ -33,7 +35,7 @@ private:
|
|||
QString m_apiKey;
|
||||
QString m_syncthingPort;
|
||||
QCoreApplication m_app;
|
||||
QProcess m_syncthingProcess;
|
||||
Data::SyncthingProcess m_syncthingProcess;
|
||||
};
|
||||
|
||||
inline const QString &SyncthingTestInstance::apiKey() const
|
||||
|
|
Loading…
Reference in New Issue