summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/calendarsync.cpp6
-rw-r--r--tests/test_calendarsync.cpp37
2 files changed, 39 insertions, 4 deletions
diff --git a/src/calendarsync.cpp b/src/calendarsync.cpp
index 2fc555f..38d0c07 100644
--- a/src/calendarsync.cpp
+++ b/src/calendarsync.cpp
@@ -38,8 +38,12 @@ CalendarSync::CalendarSync(const QString &command, int delayMs, QObject *parent)
});
connect(&m_process, &QProcess::errorOccurred, this,
[this](QProcess::ProcessError error) {
- if (error == QProcess::FailedToStart)
+ if (error == QProcess::FailedToStart) {
+ // finished() never fires for a failed start, so the queued-run flag
+ // would otherwise leak into the next successful run.
+ m_again = false;
emit finished(false, m_process.errorString());
+ }
});
}
diff --git a/tests/test_calendarsync.cpp b/tests/test_calendarsync.cpp
index e5cdee5..643a873 100644
--- a/tests/test_calendarsync.cpp
+++ b/tests/test_calendarsync.cpp
@@ -26,13 +26,19 @@
namespace {
/// A script that appends a line to `log` each run and exits with `code`.
-QString script(const QTemporaryDir &dir, int code)
+///
+/// \p sleepSeconds keeps the run alive long enough for a second schedule() to
+/// land while it is still in progress, which is the queued-run path.
+QString script(const QTemporaryDir &dir, int code, double sleepSeconds = 0)
{
const QString path = dir.filePath(QStringLiteral("sync.sh"));
+ const QString sleep = sleepSeconds > 0
+ ? QStringLiteral("sleep %1\n").arg(sleepSeconds) : QString();
QFile f(path);
f.open(QIODevice::WriteOnly);
- f.write(QStringLiteral("#!/bin/sh\necho run >> %1\necho output\nexit %2\n")
- .arg(dir.filePath(QStringLiteral("log"))).arg(code).toUtf8());
+ f.write(QStringLiteral("#!/bin/sh\necho run >> %1\n%2echo output\nexit %3\n")
+ .arg(dir.filePath(QStringLiteral("log")), sleep)
+ .arg(code).toUtf8());
f.close();
f.setPermissions(f.permissions() | QFileDevice::ExeOwner);
return path;
@@ -53,6 +59,7 @@ class TestCalendarSync : public QObject
private slots:
void aBurstOfWritesRunsOnce();
void reportsFailureWithTheOutput();
+ void aWriteDuringARunQueuesOneMore();
void anEmptyCommandNeverRuns();
};
@@ -81,13 +88,37 @@ void TestCalendarSync::reportsFailureWithTheOutput()
QVERIFY(finished.first().at(1).toString().contains(QStringLiteral("output")));
}
+void TestCalendarSync::aWriteDuringARunQueuesOneMore()
+{
+ QTemporaryDir dir;
+ // The run sleeps, so the second schedule() below lands while it is still
+ // in progress and must queue exactly one more run, not drop the write and
+ // not run endlessly.
+ CalendarSync sync(script(dir, 0, 0.3), 0);
+ QSignalSpy started(&sync, &CalendarSync::started);
+ QSignalSpy finished(&sync, &CalendarSync::finished);
+
+ sync.schedule();
+ QVERIFY(started.wait(5000)); // positive wait: the first run is underway
+ sync.schedule(); // a write during that run
+
+ QVERIFY(finished.wait(5000)); // the first run finishes
+ QVERIFY(finished.wait(5000)); // the one queued run finishes
+ QCOMPARE(finished.count(), 2);
+
+ QTest::qWait(200); // nothing else is queued
+ QCOMPARE(runs(dir), 2);
+}
+
void TestCalendarSync::anEmptyCommandNeverRuns()
{
CalendarSync sync(QString(), 0);
QSignalSpy started(&sync, &CalendarSync::started);
+ QSignalSpy finished(&sync, &CalendarSync::finished);
sync.schedule();
QTest::qWait(100);
QCOMPARE(started.count(), 0);
+ QCOMPARE(finished.count(), 0);
}
QTEST_MAIN(TestCalendarSync)