aboutsummaryrefslogtreecommitdiff
path: root/tests/Task_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Task_test.cpp')
-rw-r--r--tests/Task_test.cpp160
1 files changed, 114 insertions, 46 deletions
diff --git a/tests/Task_test.cpp b/tests/Task_test.cpp
index 80bba02f..558cd2c0 100644
--- a/tests/Task_test.cpp
+++ b/tests/Task_test.cpp
@@ -1,4 +1,6 @@
#include <QTest>
+#include <QTimer>
+#include <QThread>
#include <tasks/ConcurrentTask.h>
#include <tasks/MultipleOptionsTask.h>
@@ -11,6 +13,9 @@ class BasicTask : public Task {
friend class TaskTest;
+ public:
+ BasicTask(bool show_debug_log = true) : Task(nullptr, show_debug_log) {}
+
private:
void executeTask() override
{
@@ -30,6 +35,42 @@ class BasicTask_MultiStep : public Task {
void executeTask() override {};
};
+class BigConcurrentTask : public QThread {
+ Q_OBJECT
+
+ ConcurrentTask big_task;
+
+ void run() override
+ {
+ QTimer deadline;
+ deadline.setInterval(10000);
+ connect(&deadline, &QTimer::timeout, this, [this]{ passed_the_deadline = true; });
+ deadline.start();
+
+ // NOTE: Arbitrary value that manages to trigger a problem when there is one.
+ static const unsigned s_num_tasks = 1 << 14;
+ auto sub_tasks = new BasicTask::Ptr[s_num_tasks];
+
+ for (unsigned i = 0; i < s_num_tasks; i++) {
+ sub_tasks[i] = makeShared<BasicTask>(false);
+ big_task.addTask(sub_tasks[i]);
+ }
+
+ big_task.run();
+
+ while (!big_task.isFinished() && !passed_the_deadline)
+ QCoreApplication::processEvents();
+
+ emit finished();
+ }
+
+ public:
+ bool passed_the_deadline = false;
+
+ signals:
+ void finished();
+};
+
class TaskTest : public QObject {
Q_OBJECT
@@ -78,21 +119,21 @@ class TaskTest : public QObject {
}
void test_basicConcurrentRun(){
- BasicTask t1;
- BasicTask t2;
- BasicTask t3;
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
ConcurrentTask t;
- t.addTask(&t1);
- t.addTask(&t2);
- t.addTask(&t3);
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
QObject::connect(&t, &Task::finished, [&]{
QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
- QVERIFY(t1.wasSuccessful());
- QVERIFY(t2.wasSuccessful());
- QVERIFY(t3.wasSuccessful());
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(t2->wasSuccessful());
+ QVERIFY(t3->wasSuccessful());
});
t.start();
@@ -103,31 +144,39 @@ class TaskTest : public QObject {
// Tests if starting new tasks after the 6 initial ones is working
void test_moreConcurrentRun(){
- BasicTask t1, t2, t3, t4, t5, t6, t7, t8, t9;
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
+ auto t4 = makeShared<BasicTask>();
+ auto t5 = makeShared<BasicTask>();
+ auto t6 = makeShared<BasicTask>();
+ auto t7 = makeShared<BasicTask>();
+ auto t8 = makeShared<BasicTask>();
+ auto t9 = makeShared<BasicTask>();
ConcurrentTask t;
- t.addTask(&t1);
- t.addTask(&t2);
- t.addTask(&t3);
- t.addTask(&t4);
- t.addTask(&t5);
- t.addTask(&t6);
- t.addTask(&t7);
- t.addTask(&t8);
- t.addTask(&t9);
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
+ t.addTask(t4);
+ t.addTask(t5);
+ t.addTask(t6);
+ t.addTask(t7);
+ t.addTask(t8);
+ t.addTask(t9);
QObject::connect(&t, &Task::finished, [&]{
QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
- QVERIFY(t1.wasSuccessful());
- QVERIFY(t2.wasSuccessful());
- QVERIFY(t3.wasSuccessful());
- QVERIFY(t4.wasSuccessful());
- QVERIFY(t5.wasSuccessful());
- QVERIFY(t6.wasSuccessful());
- QVERIFY(t7.wasSuccessful());
- QVERIFY(t8.wasSuccessful());
- QVERIFY(t9.wasSuccessful());
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(t2->wasSuccessful());
+ QVERIFY(t3->wasSuccessful());
+ QVERIFY(t4->wasSuccessful());
+ QVERIFY(t5->wasSuccessful());
+ QVERIFY(t6->wasSuccessful());
+ QVERIFY(t7->wasSuccessful());
+ QVERIFY(t8->wasSuccessful());
+ QVERIFY(t9->wasSuccessful());
});
t.start();
@@ -137,21 +186,21 @@ class TaskTest : public QObject {
}
void test_basicSequentialRun(){
- BasicTask t1;
- BasicTask t2;
- BasicTask t3;
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
SequentialTask t;
- t.addTask(&t1);
- t.addTask(&t2);
- t.addTask(&t3);
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
QObject::connect(&t, &Task::finished, [&]{
QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
- QVERIFY(t1.wasSuccessful());
- QVERIFY(t2.wasSuccessful());
- QVERIFY(t3.wasSuccessful());
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(t2->wasSuccessful());
+ QVERIFY(t3->wasSuccessful());
});
t.start();
@@ -161,21 +210,21 @@ class TaskTest : public QObject {
}
void test_basicMultipleOptionsRun(){
- BasicTask t1;
- BasicTask t2;
- BasicTask t3;
+ auto t1 = makeShared<BasicTask>();
+ auto t2 = makeShared<BasicTask>();
+ auto t3 = makeShared<BasicTask>();
MultipleOptionsTask t;
- t.addTask(&t1);
- t.addTask(&t2);
- t.addTask(&t3);
+ t.addTask(t1);
+ t.addTask(t2);
+ t.addTask(t3);
QObject::connect(&t, &Task::finished, [&]{
QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
- QVERIFY(t1.wasSuccessful());
- QVERIFY(!t2.wasSuccessful());
- QVERIFY(!t3.wasSuccessful());
+ QVERIFY(t1->wasSuccessful());
+ QVERIFY(!t2->wasSuccessful());
+ QVERIFY(!t3->wasSuccessful());
});
t.start();
@@ -183,6 +232,25 @@ class TaskTest : public QObject {
return t.isFinished();
}, 1000), "Task didn't finish as it should.");
}
+
+ void test_stackOverflowInConcurrentTask()
+ {
+ QEventLoop loop;
+
+ auto thread = new BigConcurrentTask;
+ // NOTE: This is an arbitrary value, big enough to not cause problems on normal execution, but low enough
+ // so that the number of tasks that needs to get ran to potentially cause a problem isn't too big.
+ thread->setStackSize(32 * 1024);
+
+ connect(thread, &BigConcurrentTask::finished, &loop, &QEventLoop::quit);
+
+ thread->start();
+
+ loop.exec();
+
+ QVERIFY(!thread->passed_the_deadline);
+ thread->deleteLater();
+ }
};
QTEST_GUILESS_MAIN(TaskTest)