2022-10-12 14:30:24 +02:00
|
|
|
// Copyright (C) 2022 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
#include <utils/asynctask.h>
|
2023-04-30 10:08:12 +02:00
|
|
|
#include <utils/barrier.h>
|
2022-10-12 14:30:24 +02:00
|
|
|
|
|
|
|
|
#include <QtTest>
|
|
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
#include <QDeadlineTimer>
|
|
|
|
|
|
|
|
|
|
using namespace std::literals::chrono_literals;
|
|
|
|
|
|
2022-10-12 14:30:24 +02:00
|
|
|
using namespace Utils;
|
2022-12-04 08:31:14 +01:00
|
|
|
using namespace Utils::Tasking;
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-05-03 14:33:12 +02:00
|
|
|
using TestTask = Async<void>;
|
|
|
|
|
using Test = AsyncTask<void>;
|
2023-04-28 14:41:02 +02:00
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
enum class Handler {
|
|
|
|
|
Setup,
|
|
|
|
|
Done,
|
|
|
|
|
Error,
|
|
|
|
|
GroupSetup,
|
|
|
|
|
GroupDone,
|
2023-02-06 20:27:59 +01:00
|
|
|
GroupError,
|
2023-02-20 21:32:00 +01:00
|
|
|
Sync,
|
2023-04-30 10:08:12 +02:00
|
|
|
BarrierAdvance,
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using Log = QList<QPair<int, Handler>>;
|
|
|
|
|
|
|
|
|
|
struct CustomStorage
|
|
|
|
|
{
|
|
|
|
|
CustomStorage() { ++s_count; }
|
|
|
|
|
~CustomStorage() { --s_count; }
|
|
|
|
|
Log m_log;
|
|
|
|
|
static int instanceCount() { return s_count; }
|
|
|
|
|
private:
|
|
|
|
|
static int s_count;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int CustomStorage::s_count = 0;
|
2023-04-28 14:41:02 +02:00
|
|
|
static const char s_taskIdProperty[] = "__taskId";
|
|
|
|
|
|
|
|
|
|
static FutureSynchronizer *s_futureSynchronizer = nullptr;
|
2023-01-26 19:06:02 +01:00
|
|
|
|
|
|
|
|
enum class OnStart { Running, NotRunning };
|
|
|
|
|
enum class OnDone { Success, Failure };
|
|
|
|
|
|
|
|
|
|
struct TestData {
|
|
|
|
|
TreeStorage<CustomStorage> storage;
|
|
|
|
|
Group root;
|
|
|
|
|
Log expectedLog;
|
|
|
|
|
int taskCount = 0;
|
|
|
|
|
OnStart onStart = OnStart::Running;
|
|
|
|
|
OnDone onDone = OnDone::Success;
|
|
|
|
|
};
|
|
|
|
|
|
2022-10-12 14:30:24 +02:00
|
|
|
class tst_TaskTree : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
void initTestCase();
|
|
|
|
|
|
|
|
|
|
void validConstructs(); // compile test
|
2023-04-28 14:41:02 +02:00
|
|
|
void testTree_data();
|
|
|
|
|
void testTree();
|
2022-12-04 08:31:14 +01:00
|
|
|
void storageOperators();
|
2022-11-22 15:21:45 +01:00
|
|
|
void storageDestructor();
|
2022-10-12 14:30:24 +02:00
|
|
|
|
|
|
|
|
void cleanupTestCase();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void tst_TaskTree::initTestCase()
|
|
|
|
|
{
|
2023-04-28 14:41:02 +02:00
|
|
|
s_futureSynchronizer = new FutureSynchronizer;
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tst_TaskTree::cleanupTestCase()
|
|
|
|
|
{
|
2023-04-28 14:41:02 +02:00
|
|
|
delete s_futureSynchronizer;
|
|
|
|
|
s_futureSynchronizer = nullptr;
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tst_TaskTree::validConstructs()
|
|
|
|
|
{
|
2023-04-28 14:41:02 +02:00
|
|
|
const Group task {
|
2022-10-12 14:30:24 +02:00
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test([](TestTask &) {}, [](const TestTask &) {}),
|
|
|
|
|
Test([](TestTask &) {}, [](const TestTask &) {}),
|
|
|
|
|
Test([](TestTask &) {}, [](const TestTask &) {})
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group group1 {
|
2023-04-28 14:41:02 +02:00
|
|
|
task
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group group2 {
|
|
|
|
|
parallel,
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test([](TestTask &) {}, [](const TestTask &) {}),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test([](TestTask &) {}, [](const TestTask &) {}),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test([](TestTask &) {}, [](const TestTask &) {})
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test([](TestTask &) {}, [](const TestTask &) {}),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone([] {})
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
},
|
2023-04-28 14:41:02 +02:00
|
|
|
task,
|
2022-10-12 14:30:24 +02:00
|
|
|
OnGroupDone([] {}),
|
|
|
|
|
OnGroupError([] {})
|
|
|
|
|
};
|
2023-04-26 12:33:11 +02:00
|
|
|
|
2023-05-02 14:01:49 +02:00
|
|
|
const auto setupHandler = [](TestTask &) {};
|
|
|
|
|
const auto doneHandler = [](const TestTask &) {};
|
|
|
|
|
const auto errorHandler = [](const TestTask &) {};
|
|
|
|
|
|
|
|
|
|
// Not fluent interface
|
|
|
|
|
|
|
|
|
|
const Group task2 {
|
|
|
|
|
parallel,
|
|
|
|
|
Test(setupHandler),
|
|
|
|
|
Test(setupHandler, doneHandler),
|
|
|
|
|
Test(setupHandler, doneHandler, errorHandler),
|
|
|
|
|
// need to explicitly pass empty handler for done
|
|
|
|
|
Test(setupHandler, {}, errorHandler)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Fluent interface
|
|
|
|
|
|
|
|
|
|
const Group fluent {
|
|
|
|
|
parallel,
|
|
|
|
|
Test().onSetup(setupHandler),
|
|
|
|
|
Test().onSetup(setupHandler).onDone(doneHandler),
|
|
|
|
|
Test().onSetup(setupHandler).onDone(doneHandler).onError(errorHandler),
|
|
|
|
|
// possible to skip the empty done
|
|
|
|
|
Test().onSetup(setupHandler).onError(errorHandler),
|
|
|
|
|
// possible to set handlers in a different order
|
|
|
|
|
Test().onError(errorHandler).onDone(doneHandler).onSetup(setupHandler),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2023-04-26 12:33:11 +02:00
|
|
|
// When turning each of below blocks on, you should see the specific compiler error message.
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
{
|
|
|
|
|
// "Sync element: The synchronous function has to return void or bool."
|
|
|
|
|
const auto setupSync = [] { return 3; };
|
|
|
|
|
const Sync sync(setupSync);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
{
|
|
|
|
|
// "Sync element: The synchronous function can't take any arguments."
|
|
|
|
|
const auto setupSync = [](int) { };
|
|
|
|
|
const Sync sync(setupSync);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
{
|
|
|
|
|
// "Sync element: The synchronous function can't take any arguments."
|
|
|
|
|
const auto setupSync = [](int) { return true; };
|
|
|
|
|
const Sync sync(setupSync);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
static void runTask(QPromise<void> &promise, bool success, std::chrono::milliseconds sleep)
|
|
|
|
|
{
|
|
|
|
|
QDeadlineTimer deadline(sleep);
|
|
|
|
|
while (!deadline.hasExpired()) {
|
|
|
|
|
QThread::msleep(1);
|
|
|
|
|
if (promise.isCanceled())
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!success)
|
|
|
|
|
promise.future().cancel();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 08:05:21 +02:00
|
|
|
static void reportAndSleep(QPromise<bool> &promise)
|
|
|
|
|
{
|
|
|
|
|
promise.addResult(false);
|
2023-04-30 13:31:33 +02:00
|
|
|
QThread::msleep(5);
|
2023-05-02 08:05:21 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename SharedBarrierType>
|
|
|
|
|
auto setupBarrierAdvance(const TreeStorage<CustomStorage> &storage,
|
|
|
|
|
const SharedBarrierType &barrier, int taskId)
|
|
|
|
|
{
|
2023-05-03 14:33:12 +02:00
|
|
|
return [storage, barrier, taskId](Async<bool> &async) {
|
2023-05-02 08:05:21 +02:00
|
|
|
async.setFutureSynchronizer(s_futureSynchronizer);
|
|
|
|
|
async.setConcurrentCallData(reportAndSleep);
|
|
|
|
|
async.setProperty(s_taskIdProperty, taskId);
|
|
|
|
|
storage->m_log.append({taskId, Handler::Setup});
|
|
|
|
|
|
|
|
|
|
CustomStorage *currentStorage = storage.activeStorage();
|
|
|
|
|
Barrier *sharedBarrier = barrier->barrier();
|
|
|
|
|
QObject::connect(&async, &TestTask::resultReadyAt, sharedBarrier,
|
|
|
|
|
[currentStorage, sharedBarrier, taskId](int index) {
|
|
|
|
|
Q_UNUSED(index)
|
|
|
|
|
currentStorage->m_log.append({taskId, Handler::BarrierAdvance});
|
|
|
|
|
sharedBarrier->advance();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
void tst_TaskTree::testTree_data()
|
2022-10-12 14:30:24 +02:00
|
|
|
{
|
2023-01-26 19:06:02 +01:00
|
|
|
QTest::addColumn<TestData>("testData");
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2022-12-05 18:08:48 +01:00
|
|
|
TreeStorage<CustomStorage> storage;
|
|
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupTaskHelper = [storage](TestTask &task, int taskId, bool success = true,
|
|
|
|
|
std::chrono::milliseconds sleep = 0ms) {
|
|
|
|
|
task.setFutureSynchronizer(s_futureSynchronizer);
|
|
|
|
|
task.setConcurrentCallData(runTask, success, sleep);
|
|
|
|
|
task.setProperty(s_taskIdProperty, taskId);
|
|
|
|
|
storage->m_log.append({taskId, Handler::Setup});
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupTask = [setupTaskHelper](int taskId) {
|
|
|
|
|
return [=](TestTask &task) { setupTaskHelper(task, taskId); };
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupFailingTask = [setupTaskHelper](int taskId) {
|
|
|
|
|
return [=](TestTask &task) { setupTaskHelper(task, taskId, false); };
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupSleepingTask = [setupTaskHelper](int taskId, std::chrono::milliseconds sleep) {
|
|
|
|
|
return [=](TestTask &task) { setupTaskHelper(task, taskId, true, sleep); };
|
2023-02-01 00:01:46 +01:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupDynamicTask = [setupTaskHelper](int taskId, TaskAction action) {
|
|
|
|
|
return [=](TestTask &task) {
|
|
|
|
|
setupTaskHelper(task, taskId);
|
2023-01-26 19:06:02 +01:00
|
|
|
return action;
|
|
|
|
|
};
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto logDone = [storage](const TestTask &task) {
|
|
|
|
|
storage->m_log.append({task.property(s_taskIdProperty).toInt(), Handler::Done});
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto logError = [storage](const TestTask &task) {
|
|
|
|
|
storage->m_log.append({task.property(s_taskIdProperty).toInt(), Handler::Error});
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto groupSetup = [storage](int taskId) {
|
|
|
|
|
return [=] { storage->m_log.append({taskId, Handler::GroupSetup}); };
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto groupDone = [storage](int taskId) {
|
|
|
|
|
return [=] { storage->m_log.append({taskId, Handler::GroupDone}); };
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto groupError = [storage](int taskId) {
|
|
|
|
|
return [=] { storage->m_log.append({taskId, Handler::GroupError}); };
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupSync = [storage](int taskId) {
|
|
|
|
|
return [=] { storage->m_log.append({taskId, Handler::Sync}); };
|
2023-04-26 12:33:11 +02:00
|
|
|
};
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupSyncWithReturn = [storage](int taskId, bool success) {
|
|
|
|
|
return [=] { storage->m_log.append({taskId, Handler::Sync}); return success; };
|
2023-02-06 20:27:59 +01:00
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
|
|
|
|
|
const auto constructSimpleSequence = [=](const Workflow &policy) {
|
|
|
|
|
return Group {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
policy,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1), logDone),
|
|
|
|
|
Test(setupFailingTask(2), logDone, logError),
|
|
|
|
|
Test(setupTask(3), logDone),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
|
|
|
|
};
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
const auto constructDynamicHierarchy = [=](TaskAction taskAction) {
|
|
|
|
|
return Group {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1), logDone)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup([=] { return taskAction; }),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2), logDone),
|
|
|
|
|
Test(setupTask(3), logDone),
|
|
|
|
|
Test(setupTask(4), logDone)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
|
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
|
|
|
|
};
|
2023-01-09 20:52:12 +01:00
|
|
|
};
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
2023-01-31 19:33:22 +01:00
|
|
|
const Group root1 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
|
|
|
|
};
|
|
|
|
|
const Group root2 {
|
2023-01-26 19:06:02 +01:00
|
|
|
Storage(storage),
|
2023-01-31 19:33:22 +01:00
|
|
|
OnGroupSetup([] { return TaskAction::Continue; }),
|
|
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
|
|
|
|
};
|
|
|
|
|
const Group root3 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
OnGroupSetup([] { return TaskAction::StopWithDone; }),
|
|
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
|
|
|
|
};
|
|
|
|
|
const Group root4 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
OnGroupSetup([] { return TaskAction::StopWithError; }),
|
|
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-01-31 19:33:22 +01:00
|
|
|
const Log logDone {{0, Handler::GroupDone}};
|
|
|
|
|
const Log logError {{0, Handler::GroupError}};
|
2023-01-26 19:06:02 +01:00
|
|
|
QTest::newRow("Empty")
|
2023-01-31 19:33:22 +01:00
|
|
|
<< TestData{storage, root1, logDone, 0, OnStart::NotRunning, OnDone::Success};
|
|
|
|
|
QTest::newRow("EmptyContinue")
|
|
|
|
|
<< TestData{storage, root2, logDone, 0, OnStart::NotRunning, OnDone::Success};
|
|
|
|
|
QTest::newRow("EmptyDone")
|
|
|
|
|
<< TestData{storage, root3, logDone, 0, OnStart::NotRunning, OnDone::Success};
|
|
|
|
|
QTest::newRow("EmptyError")
|
|
|
|
|
<< TestData{storage, root4, logError, 0, OnStart::NotRunning, OnDone::Failure};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(1, TaskAction::StopWithDone), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(2, TaskAction::StopWithDone), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {{1, Handler::Setup}, {2, Handler::Setup}};
|
|
|
|
|
QTest::newRow("DynamicTaskDone")
|
|
|
|
|
<< TestData{storage, root, log, 2, OnStart::NotRunning, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(1, TaskAction::StopWithError), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(2, TaskAction::StopWithError), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {{1, Handler::Setup}};
|
|
|
|
|
QTest::newRow("DynamicTaskError")
|
|
|
|
|
<< TestData{storage, root, log, 2, OnStart::NotRunning, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(3, TaskAction::StopWithError), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Done},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DynamicMixed")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::Running, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
parallel,
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(3, TaskAction::StopWithError), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{2, Handler::Error}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DynamicParallel")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::NotRunning, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
parallel,
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(3, TaskAction::StopWithError), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{2, Handler::Error}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DynamicParallelGroup")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::NotRunning, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
parallel,
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError),
|
|
|
|
|
Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
|
|
|
|
OnGroupSetup([storage] {
|
|
|
|
|
storage->m_log.append({0, Handler::GroupSetup});
|
|
|
|
|
return TaskAction::StopWithError;
|
|
|
|
|
}),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(3, TaskAction::Continue), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{0, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{2, Handler::Error}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DynamicParallelGroupSetup")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::NotRunning, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
|
|
|
|
Group {
|
|
|
|
|
Group {
|
|
|
|
|
Group {
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(5), logDone, logError),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupSetup(groupSetup(5)),
|
|
|
|
|
OnGroupDone(groupDone(5))
|
|
|
|
|
},
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
|
|
|
|
OnGroupDone(groupDone(4))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupSetup(groupSetup(3)),
|
|
|
|
|
OnGroupDone(groupDone(3))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupSetup(groupSetup(2)),
|
|
|
|
|
OnGroupDone(groupDone(2))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupSetup(groupSetup(1)),
|
|
|
|
|
OnGroupDone(groupDone(1))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0))
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{5, Handler::GroupSetup},
|
|
|
|
|
{5, Handler::Setup},
|
|
|
|
|
{5, Handler::Done},
|
|
|
|
|
{5, Handler::GroupDone},
|
|
|
|
|
{4, Handler::GroupDone},
|
|
|
|
|
{3, Handler::GroupDone},
|
|
|
|
|
{2, Handler::GroupDone},
|
|
|
|
|
{1, Handler::GroupDone},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("Nested")
|
|
|
|
|
<< TestData{storage, root, log, 1, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto logDoneAnonymously = [=](const TestTask &) {
|
2023-01-26 19:06:02 +01:00
|
|
|
storage->m_log.append({0, Handler::Done});
|
|
|
|
|
};
|
|
|
|
|
const Group root {
|
2022-12-05 18:08:48 +01:00
|
|
|
Storage(storage),
|
2023-01-26 19:06:02 +01:00
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1), logDoneAnonymously),
|
|
|
|
|
Test(setupTask(2), logDoneAnonymously),
|
|
|
|
|
Test(setupTask(3), logDoneAnonymously),
|
|
|
|
|
Test(setupTask(4), logDoneAnonymously),
|
|
|
|
|
Test(setupTask(5), logDoneAnonymously),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0))
|
2022-11-16 09:06:32 +01:00
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup}, // Setup order is determined in parallel mode
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{5, Handler::Setup},
|
|
|
|
|
{0, Handler::Done}, // Done order isn't determined in parallel mode
|
|
|
|
|
{0, Handler::Done},
|
|
|
|
|
{0, Handler::Done},
|
|
|
|
|
{0, Handler::Done},
|
|
|
|
|
{0, Handler::Done},
|
|
|
|
|
{0, Handler::GroupDone}
|
2022-12-05 18:08:48 +01:00
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
QTest::newRow("Parallel")
|
|
|
|
|
<< TestData{storage, root, log, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
auto setupSubTree = [=](TaskTree &taskTree) {
|
|
|
|
|
const Group nestedRoot {
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2), logDone),
|
|
|
|
|
Test(setupTask(3), logDone),
|
|
|
|
|
Test(setupTask(4), logDone)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
taskTree.setupRoot(nestedRoot);
|
|
|
|
|
CustomStorage *activeStorage = storage.activeStorage();
|
|
|
|
|
auto collectSubLog = [activeStorage](CustomStorage *subTreeStorage){
|
|
|
|
|
activeStorage->m_log += subTreeStorage->m_log;
|
|
|
|
|
};
|
|
|
|
|
taskTree.onStorageDone(storage, collectSubLog);
|
|
|
|
|
};
|
|
|
|
|
const Group root1 {
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1), logDone),
|
|
|
|
|
Test(setupTask(2), logDone),
|
|
|
|
|
Test(setupTask(3), logDone),
|
|
|
|
|
Test(setupTask(4), logDone),
|
|
|
|
|
Test(setupTask(5), logDone),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0))
|
|
|
|
|
};
|
|
|
|
|
const Group root2 {
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(1), logDone) },
|
|
|
|
|
Group { Test(setupTask(2), logDone) },
|
|
|
|
|
Group { Test(setupTask(3), logDone) },
|
|
|
|
|
Group { Test(setupTask(4), logDone) },
|
|
|
|
|
Group { Test(setupTask(5), logDone) },
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0))
|
|
|
|
|
};
|
|
|
|
|
const Group root3 {
|
|
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1), logDone),
|
2023-01-26 19:06:02 +01:00
|
|
|
Tree(setupSubTree),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(5), logDone),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0))
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Done},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::Done},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{4, Handler::Done},
|
|
|
|
|
{5, Handler::Setup},
|
|
|
|
|
{5, Handler::Done},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("Sequential")
|
|
|
|
|
<< TestData{storage, root1, log, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("SequentialEncapsulated")
|
|
|
|
|
<< TestData{storage, root2, log, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("SequentialSubTree") // We don't inspect subtrees, so taskCount is 3, not 5.
|
|
|
|
|
<< TestData{storage, root3, log, 3, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1), logDone),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2), logDone),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(3), logDone),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4), logDone),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(5), logDone),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(5))
|
|
|
|
|
},
|
|
|
|
|
OnGroupDone(groupDone(4))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(3))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(2))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(1))
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0))
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Done},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::Done},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{4, Handler::Done},
|
|
|
|
|
{5, Handler::Setup},
|
|
|
|
|
{5, Handler::Done},
|
|
|
|
|
{5, Handler::GroupDone},
|
|
|
|
|
{4, Handler::GroupDone},
|
|
|
|
|
{3, Handler::GroupDone},
|
|
|
|
|
{2, Handler::GroupDone},
|
|
|
|
|
{1, Handler::GroupDone},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SequentialNested")
|
|
|
|
|
<< TestData{storage, root, log, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2022-12-05 18:08:48 +01:00
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1), logDone),
|
|
|
|
|
Test(setupTask(2), logDone),
|
|
|
|
|
Test(setupFailingTask(3), logDone, logError),
|
|
|
|
|
Test(setupTask(4), logDone),
|
|
|
|
|
Test(setupTask(5), logDone),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Done},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::Error},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SequentialError")
|
|
|
|
|
<< TestData{storage, root, log, 5, OnStart::Running, OnDone::Failure};
|
|
|
|
|
}
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
|
|
|
|
const Group root = constructSimpleSequence(stopOnError);
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("StopOnError")
|
|
|
|
|
<< TestData{storage, root, log, 3, OnStart::Running, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root = constructSimpleSequence(continueOnError);
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::Done},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("ContinueOnError")
|
|
|
|
|
<< TestData{storage, root, log, 3, OnStart::Running, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root = constructSimpleSequence(stopOnDone);
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("StopOnDone")
|
|
|
|
|
<< TestData{storage, root, log, 3, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root = constructSimpleSequence(continueOnDone);
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::Done},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("ContinueOnDone")
|
|
|
|
|
<< TestData{storage, root, log, 3, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
optional,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupFailingTask(1), logDone, logError),
|
|
|
|
|
Test(setupFailingTask(2), logDone, logError),
|
2023-01-26 19:06:02 +01:00
|
|
|
OnGroupDone(groupDone(0)),
|
|
|
|
|
OnGroupError(groupError(0))
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("Optional")
|
|
|
|
|
<< TestData{storage, root, log, 2, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root = constructDynamicHierarchy(TaskAction::StopWithDone);
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DynamicSetupDone")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root = constructDynamicHierarchy(TaskAction::StopWithError);
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DynamicSetupError")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::Running, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root = constructDynamicHierarchy(TaskAction::Continue);
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Done},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Done},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::Done},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{4, Handler::Done},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DynamicSetupContinue")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-27 13:36:44 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
ParallelLimit(2),
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(3))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4))
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("NestedParallel")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
ParallelLimit(2),
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(3, TaskAction::StopWithDone))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(5)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(5))
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{5, Handler::GroupSetup},
|
|
|
|
|
{5, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("NestedParallelDone")
|
|
|
|
|
<< TestData{storage, root, log, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2023-02-01 00:01:46 +01:00
|
|
|
const Group root1 {
|
2023-01-27 13:36:44 +01:00
|
|
|
ParallelLimit(2),
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(3, TaskAction::StopWithError))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4))
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(5)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(5))
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
2023-02-01 00:01:46 +01:00
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
// Inside this test the task 2 should finish first, then synchonously:
|
|
|
|
|
// - task 3 should exit setup with error
|
|
|
|
|
// - task 1 should be stopped as a consequence of error inside the group
|
|
|
|
|
// - tasks 4 and 5 should be skipped
|
2023-02-01 00:01:46 +01:00
|
|
|
const Group root2 {
|
|
|
|
|
ParallelLimit(2),
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupSleepingTask(1, 10ms))
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2))
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(3, TaskAction::StopWithError))
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4))
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(5)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(5))
|
2023-02-01 00:01:46 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
// This test ensures that the task 1 doesn't invoke its done handler,
|
|
|
|
|
// being ready while sleeping in the task's 2 done handler.
|
|
|
|
|
// Inside this test the task 2 should finish first, then synchonously:
|
|
|
|
|
// - task 3 should exit setup with error
|
|
|
|
|
// - task 1 should be stopped as a consequence of error inside the group
|
|
|
|
|
// - task 4 should be skipped
|
2023-02-01 00:01:46 +01:00
|
|
|
// - the first child group of root should finish with error
|
2023-04-28 14:41:02 +02:00
|
|
|
// - task 5 should be started (because of root's continueOnError policy)
|
2023-02-01 00:01:46 +01:00
|
|
|
const Group root3 {
|
|
|
|
|
continueOnError,
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
|
|
|
|
ParallelLimit(2),
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupSleepingTask(1, 20ms))
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2), [](const TestTask &) { QThread::msleep(10); })
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupDynamicTask(3, TaskAction::StopWithError))
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4))
|
2023-02-01 00:01:46 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(5)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(5))
|
2023-02-01 00:01:46 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log shortLog {
|
2023-01-27 13:36:44 +01:00
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
2023-02-01 00:01:46 +01:00
|
|
|
const Log longLog = shortLog + Log {{5, Handler::GroupSetup}, {5, Handler::Setup}};
|
|
|
|
|
QTest::newRow("NestedParallelError1")
|
|
|
|
|
<< TestData{storage, root1, shortLog, 5, OnStart::Running, OnDone::Failure};
|
|
|
|
|
QTest::newRow("NestedParallelError2")
|
|
|
|
|
<< TestData{storage, root2, shortLog, 5, OnStart::Running, OnDone::Failure};
|
|
|
|
|
QTest::newRow("NestedParallelError3")
|
|
|
|
|
<< TestData{storage, root3, longLog, 5, OnStart::Running, OnDone::Failure};
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
ParallelLimit(2),
|
2022-12-05 18:08:48 +01:00
|
|
|
Storage(storage),
|
2022-11-04 14:08:32 +01:00
|
|
|
Group {
|
2023-01-26 19:06:02 +01:00
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(1))
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2022-11-04 14:08:32 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-01-26 19:06:02 +01:00
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2))
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2022-11-04 14:08:32 +01:00
|
|
|
},
|
2023-01-24 11:56:30 +01:00
|
|
|
Group {
|
2023-01-26 19:06:02 +01:00
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(3))
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
},
|
2023-01-24 11:56:30 +01:00
|
|
|
Group {
|
2023-01-26 19:06:02 +01:00
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4))
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2023-01-24 11:56:30 +01:00
|
|
|
}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::Setup}
|
|
|
|
|
};
|
2023-01-27 13:36:44 +01:00
|
|
|
QTest::newRow("DeeplyNestedParallel")
|
|
|
|
|
<< TestData{storage, root, log, 4, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
ParallelLimit(2),
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(1)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(2)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupDynamicTask(3, TaskAction::StopWithDone)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(4)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(5)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(5)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{5, Handler::GroupSetup},
|
|
|
|
|
{5, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DeeplyNestedParallelDone")
|
|
|
|
|
<< TestData{storage, root, log, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
ParallelLimit(2),
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(1)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(2)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupDynamicTask(3, TaskAction::StopWithError)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(4)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(4)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
Storage(TreeStorage<CustomStorage>()),
|
|
|
|
|
OnGroupSetup(groupSetup(5)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Group { Test(setupTask(5)) }
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("DeeplyNestedParallelError")
|
|
|
|
|
<< TestData{storage, root, log, 5, OnStart::Running, OnDone::Failure};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2023-02-06 20:27:59 +01:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSync(1)),
|
|
|
|
|
Sync(setupSync(2)),
|
|
|
|
|
Sync(setupSync(3)),
|
|
|
|
|
Sync(setupSync(4)),
|
|
|
|
|
Sync(setupSync(5))
|
2023-02-06 20:27:59 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Sync},
|
|
|
|
|
{3, Handler::Sync},
|
|
|
|
|
{4, Handler::Sync},
|
|
|
|
|
{5, Handler::Sync}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SyncSequential")
|
|
|
|
|
<< TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-26 12:33:11 +02:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Sync(setupSyncWithReturn(1, true)),
|
|
|
|
|
Sync(setupSyncWithReturn(2, true)),
|
|
|
|
|
Sync(setupSyncWithReturn(3, true)),
|
|
|
|
|
Sync(setupSyncWithReturn(4, true)),
|
|
|
|
|
Sync(setupSyncWithReturn(5, true))
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Sync},
|
|
|
|
|
{3, Handler::Sync},
|
|
|
|
|
{4, Handler::Sync},
|
|
|
|
|
{5, Handler::Sync}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SyncWithReturn")
|
|
|
|
|
<< TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-06 20:27:59 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
parallel,
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSync(1)),
|
|
|
|
|
Sync(setupSync(2)),
|
|
|
|
|
Sync(setupSync(3)),
|
|
|
|
|
Sync(setupSync(4)),
|
|
|
|
|
Sync(setupSync(5))
|
2023-02-06 20:27:59 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Sync},
|
|
|
|
|
{3, Handler::Sync},
|
|
|
|
|
{4, Handler::Sync},
|
|
|
|
|
{5, Handler::Sync}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SyncParallel")
|
|
|
|
|
<< TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
parallel,
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSync(1)),
|
|
|
|
|
Sync(setupSync(2)),
|
|
|
|
|
Sync(setupSyncWithReturn(3, false)),
|
|
|
|
|
Sync(setupSync(4)),
|
|
|
|
|
Sync(setupSync(5))
|
2023-02-06 20:27:59 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Sync},
|
|
|
|
|
{3, Handler::Sync}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SyncError")
|
|
|
|
|
<< TestData{storage, root, log, 0, OnStart::NotRunning, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 21:32:00 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSync(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2)),
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSync(3)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4)),
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSync(5)),
|
2023-02-20 21:32:00 +01:00
|
|
|
OnGroupDone(groupDone(0))
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Sync},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{5, Handler::Sync},
|
|
|
|
|
{0, Handler::GroupDone}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SyncAndAsync")
|
|
|
|
|
<< TestData{storage, root, log, 2, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-26 12:33:11 +02:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Sync(setupSync(1)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2)),
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSyncWithReturn(3, false)),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(4)),
|
2023-04-26 12:33:11 +02:00
|
|
|
Sync(setupSync(5)),
|
|
|
|
|
OnGroupError(groupError(0))
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Sync},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("SyncAndAsyncError")
|
|
|
|
|
<< TestData{storage, root, log, 2, OnStart::Running, OnDone::Failure};
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 21:32:00 +01:00
|
|
|
{
|
2023-04-30 10:08:12 +02:00
|
|
|
SingleBarrier barrier;
|
2023-02-20 21:32:00 +01:00
|
|
|
|
2023-04-30 10:08:12 +02:00
|
|
|
// Test that barrier advance, triggered from inside the task described by
|
2023-05-02 08:05:21 +02:00
|
|
|
// setupBarrierAdvance, placed BEFORE the group containing the waitFor() element
|
2023-04-26 23:46:52 +02:00
|
|
|
// in the tree order, works OK in SEQUENTIAL mode.
|
|
|
|
|
const Group root1 {
|
2023-02-20 21:32:00 +01:00
|
|
|
Storage(storage),
|
2023-04-30 10:08:12 +02:00
|
|
|
Storage(barrier),
|
2023-04-26 23:46:52 +02:00
|
|
|
sequential,
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 1)),
|
2023-02-20 21:32:00 +01:00
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-30 10:08:12 +02:00
|
|
|
WaitForBarrier(barrier),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2)),
|
|
|
|
|
Test(setupTask(3))
|
2023-02-20 21:32:00 +01:00
|
|
|
}
|
|
|
|
|
};
|
2023-04-26 23:46:52 +02:00
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::Setup},
|
2023-04-30 10:08:12 +02:00
|
|
|
{1, Handler::BarrierAdvance},
|
2023-04-26 23:46:52 +02:00
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-30 10:08:12 +02:00
|
|
|
// Test that barrier advance, triggered from inside the task described by
|
|
|
|
|
// setupTaskWithCondition, placed BEFORE the group containing the waitFor() element
|
2023-04-26 23:46:52 +02:00
|
|
|
// in the tree order, works OK in PARALLEL mode.
|
|
|
|
|
const Group root2 {
|
|
|
|
|
Storage(storage),
|
2023-04-30 10:08:12 +02:00
|
|
|
Storage(barrier),
|
2023-04-26 23:46:52 +02:00
|
|
|
parallel,
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 1)),
|
2023-04-26 23:46:52 +02:00
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-30 10:08:12 +02:00
|
|
|
WaitForBarrier(barrier),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2)),
|
|
|
|
|
Test(setupTask(3))
|
2023-04-26 23:46:52 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log2 {
|
2023-02-20 21:32:00 +01:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
2023-04-30 10:08:12 +02:00
|
|
|
{1, Handler::BarrierAdvance},
|
2023-02-20 21:32:00 +01:00
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
2023-04-26 23:46:52 +02:00
|
|
|
|
2023-04-30 10:08:12 +02:00
|
|
|
// Test that barrier advance, triggered from inside the task described by
|
|
|
|
|
// setupTaskWithCondition, placed AFTER the group containing the waitFor() element
|
2023-04-26 23:46:52 +02:00
|
|
|
// in the tree order, works OK in PARALLEL mode.
|
|
|
|
|
//
|
2023-04-30 10:08:12 +02:00
|
|
|
// Notice: This won't work in SEQUENTIAL mode, since the advancing barrier, placed after the
|
2023-04-26 23:46:52 +02:00
|
|
|
// group containing the WaitFor element, has no chance to be started in SEQUENTIAL mode,
|
|
|
|
|
// as in SEQUENTIAL mode the next task may only be started after the previous one finished.
|
2023-04-30 10:08:12 +02:00
|
|
|
// In this case, the previous task (Group element) awaits for the barrier's advance to
|
2023-04-26 23:46:52 +02:00
|
|
|
// come from the not yet started next task, causing a deadlock.
|
|
|
|
|
// The minimal requirement for this scenario to succeed is to set ParallelLimit(2) or more.
|
|
|
|
|
const Group root3 {
|
|
|
|
|
Storage(storage),
|
2023-04-30 10:08:12 +02:00
|
|
|
Storage(barrier),
|
2023-04-26 23:46:52 +02:00
|
|
|
parallel,
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
2023-04-30 10:08:12 +02:00
|
|
|
WaitForBarrier(barrier),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupTask(2)),
|
|
|
|
|
Test(setupTask(3))
|
2023-04-26 23:46:52 +02:00
|
|
|
},
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 1))
|
2023-04-26 23:46:52 +02:00
|
|
|
};
|
|
|
|
|
const Log log3 {
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
2023-04-30 10:08:12 +02:00
|
|
|
{1, Handler::BarrierAdvance},
|
2023-04-26 23:46:52 +02:00
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-30 13:31:33 +02:00
|
|
|
// Test that barrier advance, triggered from inside the task described by
|
|
|
|
|
// setupBarrierAdvance, placed BEFORE the groups containing the waitFor() element
|
|
|
|
|
// in the tree order, wakes both waitFor tasks.
|
|
|
|
|
const Group root4 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Storage(barrier),
|
|
|
|
|
parallel,
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 1)),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
Test(setupTask(4))
|
|
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
Test(setupTask(5))
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log4 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{5, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test two separate single barriers.
|
|
|
|
|
|
|
|
|
|
SingleBarrier barrier2;
|
|
|
|
|
|
|
|
|
|
const Group root5 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Storage(barrier),
|
|
|
|
|
Storage(barrier2),
|
|
|
|
|
parallel,
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 0)),
|
|
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier2, 0)),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
|
|
|
|
OnGroupSetup(groupSetup(1)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
WaitForBarrier(barrier2)
|
|
|
|
|
},
|
|
|
|
|
Test(setupTask(2))
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const Log log5 {
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{0, Handler::BarrierAdvance},
|
|
|
|
|
{0, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-26 23:46:52 +02:00
|
|
|
// Notice the different log order for each scenario.
|
2023-04-30 10:08:12 +02:00
|
|
|
QTest::newRow("BarrierSequential")
|
|
|
|
|
<< TestData{storage, root1, log1, 4, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("BarrierParallelAdvanceFirst")
|
|
|
|
|
<< TestData{storage, root2, log2, 4, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("BarrierParallelWaitForFirst")
|
|
|
|
|
<< TestData{storage, root3, log3, 4, OnStart::Running, OnDone::Success};
|
2023-04-30 13:31:33 +02:00
|
|
|
QTest::newRow("BarrierParallelMultiWaitFor")
|
|
|
|
|
<< TestData{storage, root4, log4, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("BarrierParallelTwoSingleBarriers")
|
|
|
|
|
<< TestData{storage, root5, log5, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
MultiBarrier<2> barrier;
|
|
|
|
|
|
|
|
|
|
// Test that multi barrier advance, triggered from inside the tasks described by
|
|
|
|
|
// setupBarrierAdvance, placed BEFORE the group containing the waitFor() element
|
|
|
|
|
// in the tree order, works OK in SEQUENTIAL mode.
|
|
|
|
|
const Group root1 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Storage(barrier),
|
|
|
|
|
sequential,
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 1)),
|
|
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 2)),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
Test(setupTask(2)),
|
|
|
|
|
Test(setupTask(3))
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test that multi barrier advance, triggered from inside the tasks described by
|
|
|
|
|
// setupBarrierAdvance, placed BEFORE the group containing the waitFor() element
|
|
|
|
|
// in the tree order, works OK in PARALLEL mode.
|
|
|
|
|
const Group root2 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Storage(barrier),
|
|
|
|
|
parallel,
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 0)),
|
|
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 0)),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
Test(setupTask(2)),
|
|
|
|
|
Test(setupTask(3))
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log2 {
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{0, Handler::BarrierAdvance}, // Barrier advances may come in different order in
|
|
|
|
|
{0, Handler::BarrierAdvance}, // parallel mode, that's why id = 0 (same for both).
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test that multi barrier advance, triggered from inside the tasks described by
|
|
|
|
|
// setupBarrierAdvance, placed AFTER the group containing the waitFor() element
|
|
|
|
|
// in the tree order, works OK in PARALLEL mode.
|
|
|
|
|
//
|
|
|
|
|
// Notice: This won't work in SEQUENTIAL mode, since the advancing barriers, placed after
|
|
|
|
|
// the group containing the WaitFor element, has no chance to be started in SEQUENTIAL mode,
|
|
|
|
|
// as in SEQUENTIAL mode the next task may only be started after the previous one finished.
|
|
|
|
|
// In this case, the previous task (Group element) awaits for the barrier's advance to
|
|
|
|
|
// come from the not yet started next task, causing a deadlock.
|
|
|
|
|
// The minimal requirement for this scenario to succeed is to set ParallelLimit(2) or more.
|
|
|
|
|
const Group root3 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Storage(barrier),
|
|
|
|
|
parallel,
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
Test(setupTask(2)),
|
|
|
|
|
Test(setupTask(3))
|
|
|
|
|
},
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 0)),
|
|
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 0))
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
const Log log3 {
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{0, Handler::BarrierAdvance}, // Barrier advances may come in different order in
|
|
|
|
|
{0, Handler::BarrierAdvance}, // parallel mode, that's why id = 0 (same for both).
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test that multi barrier advance, triggered from inside the task described by
|
|
|
|
|
// setupBarrierAdvance, placed BEFORE the groups containing the waitFor() element
|
|
|
|
|
// in the tree order, wakes both waitFor tasks.
|
|
|
|
|
const Group root4 {
|
|
|
|
|
Storage(storage),
|
|
|
|
|
Storage(barrier),
|
|
|
|
|
parallel,
|
2023-05-03 14:33:12 +02:00
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 0)),
|
|
|
|
|
AsyncTask<bool>(setupBarrierAdvance(storage, barrier, 0)),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(2)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
Test(setupTask(4))
|
|
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
OnGroupSetup(groupSetup(3)),
|
|
|
|
|
WaitForBarrier(barrier),
|
|
|
|
|
Test(setupTask(5))
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log4 {
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{0, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{0, Handler::BarrierAdvance},
|
|
|
|
|
{0, Handler::BarrierAdvance},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{5, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Notice the different log order for each scenario.
|
|
|
|
|
QTest::newRow("MultiBarrierSequential")
|
|
|
|
|
<< TestData{storage, root1, log1, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("MultiBarrierParallelAdvanceFirst")
|
|
|
|
|
<< TestData{storage, root2, log2, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("MultiBarrierParallelWaitForFirst")
|
|
|
|
|
<< TestData{storage, root3, log3, 5, OnStart::Running, OnDone::Success};
|
|
|
|
|
QTest::newRow("MultiBarrierParallelMultiWaitFor")
|
|
|
|
|
<< TestData{storage, root4, log4, 6, OnStart::Running, OnDone::Success};
|
2023-02-20 21:32:00 +01:00
|
|
|
}
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
void tst_TaskTree::testTree()
|
2022-10-12 14:30:24 +02:00
|
|
|
{
|
2023-01-26 19:06:02 +01:00
|
|
|
QFETCH(TestData, testData);
|
2022-10-12 14:30:24 +02:00
|
|
|
|
|
|
|
|
QEventLoop eventLoop;
|
2023-01-26 19:06:02 +01:00
|
|
|
TaskTree taskTree(testData.root);
|
|
|
|
|
QCOMPARE(taskTree.taskCount(), testData.taskCount);
|
2022-10-12 14:30:24 +02:00
|
|
|
int doneCount = 0;
|
|
|
|
|
int errorCount = 0;
|
2022-12-05 18:08:48 +01:00
|
|
|
connect(&taskTree, &TaskTree::done, this, [&doneCount, &eventLoop] {
|
|
|
|
|
++doneCount;
|
|
|
|
|
eventLoop.quit();
|
|
|
|
|
});
|
|
|
|
|
connect(&taskTree, &TaskTree::errorOccurred, this, [&errorCount, &eventLoop] {
|
|
|
|
|
++errorCount;
|
|
|
|
|
eventLoop.quit();
|
|
|
|
|
});
|
|
|
|
|
Log actualLog;
|
|
|
|
|
auto collectLog = [&actualLog](CustomStorage *storage){
|
|
|
|
|
actualLog = storage->m_log;
|
|
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
taskTree.onStorageDone(testData.storage, collectLog);
|
2022-12-05 18:08:48 +01:00
|
|
|
taskTree.start();
|
2023-01-26 19:06:02 +01:00
|
|
|
const bool expectRunning = testData.onStart == OnStart::Running;
|
|
|
|
|
QCOMPARE(taskTree.isRunning(), expectRunning);
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
if (expectRunning) {
|
2022-11-25 12:35:07 +01:00
|
|
|
QTimer timer;
|
|
|
|
|
bool timedOut = false;
|
|
|
|
|
connect(&timer, &QTimer::timeout, &eventLoop, [&eventLoop, &timedOut] {
|
|
|
|
|
timedOut = true;
|
|
|
|
|
eventLoop.quit();
|
|
|
|
|
});
|
2022-12-01 15:50:03 +01:00
|
|
|
timer.setInterval(2000);
|
2022-11-25 12:35:07 +01:00
|
|
|
timer.setSingleShot(true);
|
|
|
|
|
timer.start();
|
|
|
|
|
eventLoop.exec();
|
|
|
|
|
QCOMPARE(timedOut, false);
|
2022-12-05 18:08:48 +01:00
|
|
|
QCOMPARE(taskTree.isRunning(), false);
|
2022-11-25 12:35:07 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
QCOMPARE(taskTree.progressValue(), testData.taskCount);
|
|
|
|
|
QCOMPARE(actualLog, testData.expectedLog);
|
2022-11-21 15:05:39 +01:00
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 0);
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
const bool expectSuccess = testData.onDone == OnDone::Success;
|
|
|
|
|
const int expectedDoneCount = expectSuccess ? 1 : 0;
|
|
|
|
|
const int expectedErrorCount = expectSuccess ? 0 : 1;
|
2022-10-12 14:30:24 +02:00
|
|
|
QCOMPARE(doneCount, expectedDoneCount);
|
|
|
|
|
QCOMPARE(errorCount, expectedErrorCount);
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-04 08:31:14 +01:00
|
|
|
void tst_TaskTree::storageOperators()
|
2022-11-22 15:21:45 +01:00
|
|
|
{
|
2022-12-04 08:31:14 +01:00
|
|
|
TreeStorageBase storage1 = TreeStorage<CustomStorage>();
|
|
|
|
|
TreeStorageBase storage2 = TreeStorage<CustomStorage>();
|
|
|
|
|
TreeStorageBase storage3 = storage1;
|
2022-11-22 15:21:45 +01:00
|
|
|
|
2022-12-04 08:31:14 +01:00
|
|
|
QVERIFY(storage1 == storage3);
|
|
|
|
|
QVERIFY(storage1 != storage2);
|
|
|
|
|
QVERIFY(storage2 != storage3);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 00:01:46 +01:00
|
|
|
// This test checks whether a running task tree may be safely destructed.
|
2023-02-21 12:05:18 +01:00
|
|
|
// It also checks whether the destructor of a task tree deletes properly the storage created
|
|
|
|
|
// while starting the task tree. When running task tree is destructed, the storage done
|
|
|
|
|
// handler shouldn't be invoked.
|
2022-12-04 08:31:14 +01:00
|
|
|
void tst_TaskTree::storageDestructor()
|
|
|
|
|
{
|
2023-02-21 12:05:18 +01:00
|
|
|
bool setupCalled = false;
|
|
|
|
|
const auto setupHandler = [&setupCalled](CustomStorage *) {
|
|
|
|
|
setupCalled = true;
|
|
|
|
|
};
|
|
|
|
|
bool doneCalled = false;
|
|
|
|
|
const auto doneHandler = [&doneCalled](CustomStorage *) {
|
|
|
|
|
doneCalled = true;
|
|
|
|
|
};
|
2022-11-22 15:21:45 +01:00
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 0);
|
|
|
|
|
{
|
2023-02-21 12:05:18 +01:00
|
|
|
TreeStorage<CustomStorage> storage;
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto setupSleepingTask = [](TestTask &task) {
|
|
|
|
|
task.setFutureSynchronizer(s_futureSynchronizer);
|
|
|
|
|
task.setConcurrentCallData(runTask, true, 1000ms);
|
2022-11-22 15:21:45 +01:00
|
|
|
};
|
|
|
|
|
const Group root {
|
2023-02-21 12:05:18 +01:00
|
|
|
Storage(storage),
|
2023-04-28 14:41:02 +02:00
|
|
|
Test(setupSleepingTask)
|
2022-11-22 15:21:45 +01:00
|
|
|
};
|
|
|
|
|
|
2023-02-21 12:05:18 +01:00
|
|
|
TaskTree taskTree(root);
|
2022-11-22 15:21:45 +01:00
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 0);
|
2023-02-21 12:05:18 +01:00
|
|
|
taskTree.onStorageSetup(storage, setupHandler);
|
|
|
|
|
taskTree.onStorageDone(storage, doneHandler);
|
|
|
|
|
taskTree.start();
|
2022-11-22 15:21:45 +01:00
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 1);
|
2023-04-28 14:41:02 +02:00
|
|
|
QThread::msleep(5); // Give the sleeping task a change to start
|
2022-11-22 15:21:45 +01:00
|
|
|
}
|
|
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 0);
|
2023-02-21 12:05:18 +01:00
|
|
|
QVERIFY(setupCalled);
|
|
|
|
|
QVERIFY(!doneCalled);
|
2022-11-22 15:21:45 +01:00
|
|
|
}
|
|
|
|
|
|
2022-10-12 14:30:24 +02:00
|
|
|
QTEST_GUILESS_MAIN(tst_TaskTree)
|
|
|
|
|
|
|
|
|
|
#include "tst_tasktree.moc"
|