fix: Task test memory leaks again
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
5fe9a7a6c3
commit
4dbcedd03f
@ -95,18 +95,23 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND DEBUG_ADDRESS_SANITIZER)
|
||||
# using clang with clang-cl front end
|
||||
message(STATUS "Address Sanitizer available on Clang MSVC frontend")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /O1 /Oy-")
|
||||
else()
|
||||
# AppleClang and Clang
|
||||
message(STATUS "Address Sanitizer available on Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer")
|
||||
endif()
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
# GCC
|
||||
message(STATUS "Address Sanitizer available on GCC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer")
|
||||
link_libraries("asan")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
message(STATUS "Address Sanitizer available on MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /O1 /Oy-")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /O1 /Oy-")
|
||||
else()
|
||||
message(STATUS "Address Sanitizer not available on compiler ${CMAKE_CXX_COMPILER_ID}")
|
||||
endif()
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <QTest>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include <tasks/ConcurrentTask.h>
|
||||
#include <tasks/MultipleOptionsTask.h>
|
||||
@ -19,10 +19,7 @@ class BasicTask : public Task {
|
||||
BasicTask(bool show_debug_log = true) : Task(nullptr, show_debug_log) {}
|
||||
|
||||
private:
|
||||
void executeTask() override
|
||||
{
|
||||
emitSucceeded();
|
||||
};
|
||||
void executeTask() override { emitSucceeded(); };
|
||||
};
|
||||
|
||||
/* Does nothing. Only used for testing. */
|
||||
@ -34,7 +31,7 @@ class BasicTask_MultiStep : public Task {
|
||||
private:
|
||||
auto isMultiStep() const -> bool override { return true; }
|
||||
|
||||
void executeTask() override {};
|
||||
void executeTask() override{};
|
||||
};
|
||||
|
||||
class BigConcurrentTask : public ConcurrentTask {
|
||||
@ -44,7 +41,7 @@ class BigConcurrentTask : public ConcurrentTask {
|
||||
{
|
||||
// This is here only to help fill the stack a bit more quickly (if there's an issue, of course :^))
|
||||
// Each tasks thus adds 1024 * 4 bytes to the stack, at the very least.
|
||||
[[maybe_unused]] volatile std::array<uint32_t, 1024> some_data_on_the_stack {};
|
||||
[[maybe_unused]] volatile std::array<uint32_t, 1024> some_data_on_the_stack{};
|
||||
|
||||
ConcurrentTask::startNext();
|
||||
}
|
||||
@ -59,28 +56,28 @@ class BigConcurrentTaskThread : public QThread {
|
||||
{
|
||||
QTimer deadline;
|
||||
deadline.setInterval(10000);
|
||||
connect(&deadline, &QTimer::timeout, this, [this]{ passed_the_deadline = true; });
|
||||
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.
|
||||
// Considering each tasks, in a problematic state, adds 1024 * 4 bytes to the stack,
|
||||
// this number is enough to fill up 16 MiB of stack, more than enough to cause a problem.
|
||||
static const unsigned s_num_tasks = 1 << 12;
|
||||
auto sub_tasks = new BasicTask::Ptr[s_num_tasks];
|
||||
{
|
||||
auto sub_tasks = std::array<BasicTask::Ptr, s_num_tasks>();
|
||||
|
||||
for (unsigned i = 0; i < s_num_tasks; i++) {
|
||||
auto sub_task = makeShared<BasicTask>(false);
|
||||
sub_tasks[i] = sub_task;
|
||||
big_task.addTask(sub_task);
|
||||
}
|
||||
for (unsigned i = 0; i < s_num_tasks; i++) {
|
||||
auto sub_task = makeShared<BasicTask>(false);
|
||||
sub_tasks[i] = sub_task;
|
||||
big_task.addTask(sub_task);
|
||||
}
|
||||
|
||||
big_task.run();
|
||||
|
||||
while (!big_task.isFinished() && !passed_the_deadline)
|
||||
QCoreApplication::processEvents();
|
||||
big_task.run();
|
||||
|
||||
while (!big_task.isFinished() && !passed_the_deadline)
|
||||
QCoreApplication::processEvents();
|
||||
} // drop before emit
|
||||
emit finished();
|
||||
delete[] sub_tasks;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -94,9 +91,10 @@ class TaskTest : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void test_SetStatus_NoMultiStep(){
|
||||
void test_SetStatus_NoMultiStep()
|
||||
{
|
||||
BasicTask t;
|
||||
QString status {"test status"};
|
||||
QString status{ "test status" };
|
||||
|
||||
t.setStatus(status);
|
||||
|
||||
@ -104,9 +102,10 @@ class TaskTest : public QObject {
|
||||
QCOMPARE(t.getStepProgress().isEmpty(), TaskStepProgressList{}.isEmpty());
|
||||
}
|
||||
|
||||
void test_SetStatus_MultiStep(){
|
||||
void test_SetStatus_MultiStep()
|
||||
{
|
||||
BasicTask_MultiStep t;
|
||||
QString status {"test status"};
|
||||
QString status{ "test status" };
|
||||
|
||||
t.setStatus(status);
|
||||
|
||||
@ -116,7 +115,8 @@ class TaskTest : public QObject {
|
||||
QCOMPARE(t.getStepProgress().isEmpty(), TaskStepProgressList{}.isEmpty());
|
||||
}
|
||||
|
||||
void test_SetProgress(){
|
||||
void test_SetProgress()
|
||||
{
|
||||
BasicTask t;
|
||||
int current = 42;
|
||||
int total = 207;
|
||||
@ -127,17 +127,18 @@ class TaskTest : public QObject {
|
||||
QCOMPARE(t.getTotalProgress(), total);
|
||||
}
|
||||
|
||||
void test_basicRun(){
|
||||
void test_basicRun()
|
||||
{
|
||||
BasicTask t;
|
||||
QObject::connect(&t, &Task::finished, [&]{ QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
||||
QObject::connect(&t, &Task::finished,
|
||||
[&] { QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been."); });
|
||||
t.start();
|
||||
|
||||
QVERIFY2(QTest::qWaitFor([&]() {
|
||||
return t.isFinished();
|
||||
}, 1000), "Task didn't finish as it should.");
|
||||
QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
|
||||
}
|
||||
|
||||
void test_basicConcurrentRun(){
|
||||
void test_basicConcurrentRun()
|
||||
{
|
||||
auto t1 = makeShared<BasicTask>();
|
||||
auto t2 = makeShared<BasicTask>();
|
||||
auto t3 = makeShared<BasicTask>();
|
||||
@ -148,21 +149,20 @@ class TaskTest : public QObject {
|
||||
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());
|
||||
QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3] {
|
||||
QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
|
||||
QVERIFY(t1->wasSuccessful());
|
||||
QVERIFY(t2->wasSuccessful());
|
||||
QVERIFY(t3->wasSuccessful());
|
||||
});
|
||||
|
||||
t.start();
|
||||
QVERIFY2(QTest::qWaitFor([&]() {
|
||||
return t.isFinished();
|
||||
}, 1000), "Task didn't finish as it should.");
|
||||
QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
|
||||
}
|
||||
|
||||
// Tests if starting new tasks after the 6 initial ones is working
|
||||
void test_moreConcurrentRun(){
|
||||
void test_moreConcurrentRun()
|
||||
{
|
||||
auto t1 = makeShared<BasicTask>();
|
||||
auto t2 = makeShared<BasicTask>();
|
||||
auto t3 = makeShared<BasicTask>();
|
||||
@ -185,26 +185,25 @@ class TaskTest : public QObject {
|
||||
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());
|
||||
QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9] {
|
||||
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());
|
||||
});
|
||||
|
||||
t.start();
|
||||
QVERIFY2(QTest::qWaitFor([&]() {
|
||||
return t.isFinished();
|
||||
}, 1000), "Task didn't finish as it should.");
|
||||
QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
|
||||
}
|
||||
|
||||
void test_basicSequentialRun(){
|
||||
void test_basicSequentialRun()
|
||||
{
|
||||
auto t1 = makeShared<BasicTask>();
|
||||
auto t2 = makeShared<BasicTask>();
|
||||
auto t3 = makeShared<BasicTask>();
|
||||
@ -215,20 +214,19 @@ class TaskTest : public QObject {
|
||||
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());
|
||||
QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3] {
|
||||
QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
|
||||
QVERIFY(t1->wasSuccessful());
|
||||
QVERIFY(t2->wasSuccessful());
|
||||
QVERIFY(t3->wasSuccessful());
|
||||
});
|
||||
|
||||
t.start();
|
||||
QVERIFY2(QTest::qWaitFor([&]() {
|
||||
return t.isFinished();
|
||||
}, 1000), "Task didn't finish as it should.");
|
||||
QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
|
||||
}
|
||||
|
||||
void test_basicMultipleOptionsRun(){
|
||||
void test_basicMultipleOptionsRun()
|
||||
{
|
||||
auto t1 = makeShared<BasicTask>();
|
||||
auto t2 = makeShared<BasicTask>();
|
||||
auto t3 = makeShared<BasicTask>();
|
||||
@ -239,17 +237,15 @@ class TaskTest : public QObject {
|
||||
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());
|
||||
QObject::connect(&t, &Task::finished, [&t, &t1, &t2, &t3] {
|
||||
QVERIFY2(t.wasSuccessful(), "Task finished but was not successful when it should have been.");
|
||||
QVERIFY(t1->wasSuccessful());
|
||||
QVERIFY(!t2->wasSuccessful());
|
||||
QVERIFY(!t3->wasSuccessful());
|
||||
});
|
||||
|
||||
t.start();
|
||||
QVERIFY2(QTest::qWaitFor([&]() {
|
||||
return t.isFinished();
|
||||
}, 1000), "Task didn't finish as it should.");
|
||||
QVERIFY2(QTest::qWaitFor([&]() { return t.isFinished(); }, 1000), "Task didn't finish as it should.");
|
||||
}
|
||||
|
||||
void test_stackOverflowInConcurrentTask()
|
||||
|
Loading…
x
Reference in New Issue
Block a user