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-05-27 17:20:40 +02:00
|
|
|
#include <tasking/barrier.h>
|
2023-11-06 08:29:33 +01:00
|
|
|
#include <tasking/concurrentcall.h>
|
2022-10-12 14:30:24 +02:00
|
|
|
|
|
|
|
|
#include <QtTest>
|
2023-11-04 23:51:17 +01:00
|
|
|
#include <QHash>
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-05-10 19:54:52 +02:00
|
|
|
using namespace Tasking;
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-05-28 22:47:59 +02:00
|
|
|
using namespace std::chrono;
|
|
|
|
|
using namespace std::chrono_literals;
|
2023-05-27 17:20:40 +02:00
|
|
|
|
|
|
|
|
using TaskObject = milliseconds;
|
2023-05-28 22:47:59 +02:00
|
|
|
using TestTask = TimeoutTask;
|
2023-04-28 14:41:02 +02:00
|
|
|
|
2023-05-26 11:05:35 +02:00
|
|
|
namespace PrintableEnums {
|
|
|
|
|
|
|
|
|
|
Q_NAMESPACE
|
|
|
|
|
|
2023-11-04 21:46:10 +01:00
|
|
|
// TODO: Is it possible to check for synchronous invocation of subsequent events, so that
|
2024-01-02 11:32:10 +01:00
|
|
|
// we may be sure that the control didn't go back to the main event loop between 2 events?
|
2023-11-04 21:46:10 +01:00
|
|
|
// In theory: yes! We can add a signal / handler to the task tree sent before / after
|
|
|
|
|
// receiving done signal from each task!
|
|
|
|
|
// TODO: Check if the TaskTree's main guard isn't locked when receiving done signal from each task.
|
|
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
enum class Handler {
|
|
|
|
|
Setup,
|
2023-11-03 10:36:11 +01:00
|
|
|
Success,
|
2023-01-26 19:06:02 +01:00
|
|
|
Error,
|
2023-11-03 10:36:11 +01:00
|
|
|
Canceled,
|
2023-01-26 19:06:02 +01:00
|
|
|
GroupSetup,
|
2023-11-03 10:36:11 +01:00
|
|
|
GroupSuccess,
|
2023-11-04 09:44:33 +01:00
|
|
|
GroupError,
|
|
|
|
|
GroupCanceled,
|
2023-11-04 21:46:10 +01:00
|
|
|
TweakSetupToSuccess,
|
|
|
|
|
TweakSetupToError,
|
|
|
|
|
TweakSetupToContinue,
|
|
|
|
|
TweakDoneToSuccess,
|
|
|
|
|
TweakDoneToError,
|
2023-02-20 21:32:00 +01:00
|
|
|
Sync,
|
2023-05-29 00:13:12 +02:00
|
|
|
BarrierAdvance,
|
2023-11-04 23:51:17 +01:00
|
|
|
Timeout,
|
|
|
|
|
Storage
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-05-26 11:05:35 +02:00
|
|
|
Q_ENUM_NS(Handler);
|
|
|
|
|
|
2023-11-06 08:29:33 +01:00
|
|
|
enum class ThreadResult
|
|
|
|
|
{
|
|
|
|
|
Success,
|
|
|
|
|
FailOnTaskCountCheck,
|
|
|
|
|
FailOnRunningCheck,
|
|
|
|
|
FailOnProgressCheck,
|
|
|
|
|
FailOnLogCheck,
|
|
|
|
|
FailOnDoneStatusCheck,
|
|
|
|
|
Canceled
|
|
|
|
|
};
|
|
|
|
|
Q_ENUM_NS(ThreadResult);
|
|
|
|
|
|
2023-05-26 11:05:35 +02:00
|
|
|
} // namespace PrintableEnums
|
|
|
|
|
|
|
|
|
|
using namespace PrintableEnums;
|
2023-01-26 19:06:02 +01:00
|
|
|
|
|
|
|
|
using Log = QList<QPair<int, Handler>>;
|
|
|
|
|
|
|
|
|
|
struct CustomStorage
|
|
|
|
|
{
|
2023-11-06 08:29:33 +01:00
|
|
|
CustomStorage() { s_count.fetch_add(1); }
|
|
|
|
|
~CustomStorage() { s_count.fetch_add(-1); }
|
2023-01-26 19:06:02 +01:00
|
|
|
Log m_log;
|
2023-11-06 08:29:33 +01:00
|
|
|
static int instanceCount() { return s_count.load(); }
|
2023-01-26 19:06:02 +01:00
|
|
|
private:
|
2023-11-06 08:29:33 +01:00
|
|
|
static std::atomic_int s_count;
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
|
2023-11-06 08:29:33 +01:00
|
|
|
std::atomic_int CustomStorage::s_count = 0;
|
2023-04-28 14:41:02 +02:00
|
|
|
|
2023-11-06 08:29:33 +01:00
|
|
|
struct TestData
|
|
|
|
|
{
|
2023-11-19 14:50:55 +01:00
|
|
|
Storage<CustomStorage> storage;
|
2023-01-26 19:06:02 +01:00
|
|
|
Group root;
|
|
|
|
|
Log expectedLog;
|
|
|
|
|
int taskCount = 0;
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith onDone = DoneWith::Success;
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
|
2023-05-10 21:38:41 +02:00
|
|
|
class tst_Tasking : public QObject
|
2022-10-12 14:30:24 +02:00
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
void validConstructs(); // compile test
|
2023-11-05 14:26:26 +01:00
|
|
|
void runtimeCheck(); // checks done on runtime
|
2023-04-28 14:41:02 +02:00
|
|
|
void testTree_data();
|
|
|
|
|
void testTree();
|
2023-11-06 08:29:33 +01:00
|
|
|
void testInThread_data();
|
|
|
|
|
void testInThread();
|
2023-08-31 20:10:31 +02:00
|
|
|
void storageIO_data();
|
|
|
|
|
void storageIO();
|
2022-12-04 08:31:14 +01:00
|
|
|
void storageOperators();
|
2022-11-22 15:21:45 +01:00
|
|
|
void storageDestructor();
|
2024-01-06 13:54:32 +01:00
|
|
|
void restart();
|
2024-01-14 15:06:27 +01:00
|
|
|
void destructorOfTaskEmittingDone();
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
|
|
|
|
|
2023-05-10 21:38:41 +02:00
|
|
|
void tst_Tasking::validConstructs()
|
2022-10-12 14:30:24 +02:00
|
|
|
{
|
2023-04-28 14:41:02 +02:00
|
|
|
const Group task {
|
2022-10-12 14:30:24 +02:00
|
|
|
parallel,
|
2023-11-03 09:42:55 +01:00
|
|
|
TestTask([](TaskObject &) {}, [](const TaskObject &, DoneWith) {}),
|
2023-11-02 23:19:49 +01:00
|
|
|
TestTask([](TaskObject &) {}, [](const TaskObject &) {}),
|
2023-11-03 14:42:55 +01:00
|
|
|
TestTask([](TaskObject &) {}, [](DoneWith) {}),
|
2023-11-02 23:34:52 +01:00
|
|
|
TestTask([](TaskObject &) {}, [] {}),
|
|
|
|
|
TestTask([](TaskObject &) {}, {}),
|
|
|
|
|
TestTask([](TaskObject &) {}),
|
2023-11-03 09:42:55 +01:00
|
|
|
TestTask({}, [](const TaskObject &, DoneWith) {}),
|
2023-11-02 23:34:52 +01:00
|
|
|
TestTask({}, [](const TaskObject &) {}),
|
2023-11-03 14:42:55 +01:00
|
|
|
TestTask({}, [](DoneWith) {}),
|
2023-11-02 23:34:52 +01:00
|
|
|
TestTask({}, [] {}),
|
|
|
|
|
TestTask({}, {}),
|
2023-11-03 14:42:55 +01:00
|
|
|
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-11-03 09:42:55 +01:00
|
|
|
TestTask([](TaskObject &) {}, [](const TaskObject &, DoneWith) {}),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-11-02 23:19:49 +01:00
|
|
|
TestTask([](TaskObject &) {}, [](const TaskObject &) {}),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-11-02 23:19:49 +01:00
|
|
|
TestTask([](TaskObject &) {}, [] {})
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-11-03 09:42:55 +01:00
|
|
|
TestTask([](TaskObject &) {}, [](const TaskObject &, DoneWith) {}),
|
2023-05-02 12:31:16 +02:00
|
|
|
onGroupDone([] {})
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
},
|
2023-04-28 14:41:02 +02:00
|
|
|
task,
|
2023-11-03 18:50:32 +01:00
|
|
|
onGroupDone([] {})
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-04-26 12:33:11 +02:00
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const auto setupHandler = [](TaskObject &) {};
|
2023-10-31 17:03:48 +01:00
|
|
|
const auto finishHandler = [](const TaskObject &) {};
|
2023-05-27 17:20:40 +02:00
|
|
|
const auto errorHandler = [](const TaskObject &) {};
|
2023-11-03 09:42:55 +01:00
|
|
|
const auto doneHandler = [](const TaskObject &, DoneWith) {};
|
2023-05-02 14:01:49 +02:00
|
|
|
|
|
|
|
|
const Group task2 {
|
|
|
|
|
parallel,
|
2023-11-02 15:29:16 +01:00
|
|
|
TestTask(),
|
2023-05-28 22:47:59 +02:00
|
|
|
TestTask(setupHandler),
|
2023-11-02 18:47:38 +01:00
|
|
|
TestTask(setupHandler, finishHandler, CallDoneIf::Success),
|
2023-05-28 22:47:59 +02:00
|
|
|
TestTask(setupHandler, doneHandler),
|
2023-05-02 14:01:49 +02:00
|
|
|
// need to explicitly pass empty handler for done
|
2023-11-02 18:47:38 +01:00
|
|
|
TestTask(setupHandler, errorHandler, CallDoneIf::Error),
|
|
|
|
|
TestTask({}, finishHandler, CallDoneIf::Success),
|
|
|
|
|
TestTask({}, errorHandler, CallDoneIf::Error)
|
2023-05-02 14:01:49 +02:00
|
|
|
};
|
|
|
|
|
|
2023-04-26 12:33:11 +02:00
|
|
|
// When turning each of below blocks on, you should see the specific compiler error message.
|
|
|
|
|
|
2023-11-04 17:52:18 +01:00
|
|
|
// Sync handler needs to take no arguments and has to return void or bool.
|
2023-04-26 12:33:11 +02:00
|
|
|
#if 0
|
2023-11-04 17:52:18 +01:00
|
|
|
Sync([] { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
Sync([](int) { });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
Sync([](int) { return true; });
|
2023-04-26 12:33:11 +02:00
|
|
|
#endif
|
|
|
|
|
|
2023-11-04 17:52:18 +01:00
|
|
|
// Group setup handler needs to take no arguments and has to return void or SetupResult.
|
2023-04-26 12:33:11 +02:00
|
|
|
#if 0
|
2023-11-04 17:52:18 +01:00
|
|
|
onGroupSetup([] { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
onGroupSetup([](int) { });
|
2023-04-26 12:33:11 +02:00
|
|
|
#endif
|
|
|
|
|
|
2023-11-04 17:52:18 +01:00
|
|
|
// Group done handler needs to take (DoneWith) or (void) as an argument and has to
|
|
|
|
|
// return void or bool.
|
2023-04-26 12:33:11 +02:00
|
|
|
#if 0
|
2023-11-04 17:52:18 +01:00
|
|
|
onGroupDone([] { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
onGroupDone([](DoneWith) { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
onGroupDone([](int) { });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
onGroupDone([](DoneWith, int) { });
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Task setup handler needs to take (Task &) as an argument and has to return void or
|
|
|
|
|
// SetupResult.
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask([] {});
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask([] { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask([](TaskObject &) { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask([](TaskObject &, int) { return SetupResult::Continue; });
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Task done handler needs to take (const Task &, DoneWith), (const Task &),
|
|
|
|
|
// (DoneWith) or (void) as arguments and has to return void or bool.
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](const TaskObject &, DoneWith) { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](const TaskObject &) { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [] { return 7; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](const TaskObject &, DoneWith, int) {});
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](const TaskObject &, int) {});
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](DoneWith, int) {});
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](int) {});
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](const TaskObject &, DoneWith, int) { return true; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](const TaskObject &, int) { return true; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](DoneWith, int) { return true; });
|
|
|
|
|
#endif
|
|
|
|
|
#if 0
|
|
|
|
|
TestTask({}, [](int) { return true; });
|
2023-04-26 12:33:11 +02:00
|
|
|
#endif
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-05 14:26:26 +01:00
|
|
|
void tst_Tasking::runtimeCheck()
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
QTest::ignoreMessage(QtDebugMsg, QRegularExpression("^SOFT ASSERT: "));
|
|
|
|
|
QTest::ignoreMessage(QtWarningMsg,
|
|
|
|
|
"Can't add the same storage into one Group twice, skipping...");
|
2023-11-19 14:50:55 +01:00
|
|
|
const Storage<int> storage;
|
2023-11-05 14:26:26 +01:00
|
|
|
|
|
|
|
|
Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
storage,
|
2023-11-05 14:26:26 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
QTest::ignoreMessage(QtDebugMsg, QRegularExpression("^SOFT ASSERT: "));
|
|
|
|
|
QTest::ignoreMessage(QtWarningMsg,
|
|
|
|
|
"Can't add the same storage into one Group twice, skipping...");
|
2023-11-19 14:50:55 +01:00
|
|
|
const Storage<int> storage1;
|
2023-11-05 14:26:26 +01:00
|
|
|
const auto storage2 = storage1;
|
|
|
|
|
|
|
|
|
|
Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage1,
|
|
|
|
|
storage2,
|
2023-11-05 14:26:26 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
QTest::ignoreMessage(QtDebugMsg, QRegularExpression("^SOFT ASSERT: "));
|
|
|
|
|
QTest::ignoreMessage(QtWarningMsg,
|
|
|
|
|
"Group setup handler redefinition, overriding...");
|
|
|
|
|
Group {
|
|
|
|
|
onGroupSetup([] {}),
|
|
|
|
|
onGroupSetup([] {}),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
QTest::ignoreMessage(QtDebugMsg, QRegularExpression("^SOFT ASSERT: "));
|
|
|
|
|
QTest::ignoreMessage(QtWarningMsg,
|
|
|
|
|
"Group done handler redefinition, overriding...");
|
|
|
|
|
Group {
|
|
|
|
|
onGroupDone([] {}),
|
|
|
|
|
onGroupDone([] {}),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
QTest::ignoreMessage(QtDebugMsg, QRegularExpression("^SOFT ASSERT: "));
|
|
|
|
|
QTest::ignoreMessage(QtWarningMsg,
|
|
|
|
|
"Group execution mode redefinition, overriding...");
|
|
|
|
|
Group {
|
|
|
|
|
sequential,
|
|
|
|
|
sequential,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
QTest::ignoreMessage(QtDebugMsg, QRegularExpression("^SOFT ASSERT: "));
|
|
|
|
|
QTest::ignoreMessage(QtWarningMsg,
|
|
|
|
|
"Group workflow policy redefinition, overriding...");
|
|
|
|
|
Group {
|
|
|
|
|
stopOnError,
|
|
|
|
|
stopOnError,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
class TickAndDone : public QObject
|
2023-04-28 14:41:02 +02:00
|
|
|
{
|
2023-05-27 17:20:40 +02:00
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
void setInterval(const milliseconds &interval) { m_interval = interval; }
|
|
|
|
|
void start() {
|
|
|
|
|
QTimer::singleShot(0, this, [this] {
|
|
|
|
|
emit tick();
|
|
|
|
|
QTimer::singleShot(m_interval, this, &TickAndDone::done);
|
|
|
|
|
});
|
2023-04-28 14:41:02 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
signals:
|
|
|
|
|
void tick();
|
|
|
|
|
void done();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
milliseconds m_interval;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class TickAndDoneTaskAdapter : public TaskAdapter<TickAndDone>
|
2023-05-02 08:05:21 +02:00
|
|
|
{
|
2023-05-27 17:20:40 +02:00
|
|
|
public:
|
|
|
|
|
TickAndDoneTaskAdapter() { connect(task(), &TickAndDone::done, this,
|
2023-11-15 10:33:31 +01:00
|
|
|
[this] { emit done(DoneResult::Success); }); }
|
2023-05-27 17:20:40 +02:00
|
|
|
void start() final { task()->start(); }
|
2023-05-02 08:05:21 +02:00
|
|
|
};
|
|
|
|
|
|
2023-08-17 11:08:21 +02:00
|
|
|
using TickAndDoneTask = CustomTask<TickAndDoneTaskAdapter>;
|
2023-05-27 17:20:40 +02:00
|
|
|
|
2023-05-02 08:05:21 +02:00
|
|
|
template <typename SharedBarrierType>
|
2023-11-19 14:50:55 +01:00
|
|
|
GroupItem createBarrierAdvance(const Storage<CustomStorage> &storage,
|
2023-05-29 20:16:19 +02:00
|
|
|
const SharedBarrierType &barrier, int taskId)
|
2023-05-02 08:05:21 +02:00
|
|
|
{
|
2023-05-27 17:20:40 +02:00
|
|
|
return TickAndDoneTask([storage, barrier, taskId](TickAndDone &tickAndDone) {
|
|
|
|
|
tickAndDone.setInterval(1ms);
|
2023-05-02 08:05:21 +02:00
|
|
|
storage->m_log.append({taskId, Handler::Setup});
|
|
|
|
|
|
|
|
|
|
CustomStorage *currentStorage = storage.activeStorage();
|
|
|
|
|
Barrier *sharedBarrier = barrier->barrier();
|
2023-05-27 17:20:40 +02:00
|
|
|
QObject::connect(&tickAndDone, &TickAndDone::tick, sharedBarrier,
|
|
|
|
|
[currentStorage, sharedBarrier, taskId] {
|
2023-05-02 08:05:21 +02:00
|
|
|
currentStorage->m_log.append({taskId, Handler::BarrierAdvance});
|
|
|
|
|
sharedBarrier->advance();
|
|
|
|
|
});
|
2023-05-27 17:20:40 +02:00
|
|
|
});
|
2023-05-02 08:05:21 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-06 18:52:19 +01:00
|
|
|
static Handler resultToGroupHandler(DoneWith doneWith)
|
2023-11-03 18:50:32 +01:00
|
|
|
{
|
2023-11-06 18:52:19 +01:00
|
|
|
switch (doneWith) {
|
|
|
|
|
case DoneWith::Success: return Handler::GroupSuccess;
|
|
|
|
|
case DoneWith::Error: return Handler::GroupError;
|
|
|
|
|
case DoneWith::Cancel: return Handler::GroupCanceled;
|
2023-11-04 09:44:33 +01:00
|
|
|
}
|
|
|
|
|
return Handler::GroupCanceled;
|
2023-11-03 18:50:32 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-06 18:52:19 +01:00
|
|
|
static Handler toTweakSetupHandler(SetupResult result)
|
2023-11-04 21:46:10 +01:00
|
|
|
{
|
|
|
|
|
switch (result) {
|
2023-11-06 18:52:19 +01:00
|
|
|
case SetupResult::Continue: return Handler::TweakSetupToContinue;
|
|
|
|
|
case SetupResult::StopWithSuccess: return Handler::TweakSetupToSuccess;
|
|
|
|
|
case SetupResult::StopWithError: return Handler::TweakSetupToError;
|
2023-11-04 21:46:10 +01:00
|
|
|
}
|
|
|
|
|
return Handler::TweakSetupToContinue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 18:52:19 +01:00
|
|
|
static Handler toTweakDoneHandler(DoneResult result)
|
2023-11-06 17:48:56 +01:00
|
|
|
{
|
|
|
|
|
return result == DoneResult::Success ? Handler::TweakDoneToSuccess : Handler::TweakDoneToError;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-13 13:01:55 +01:00
|
|
|
static TestData storageShadowingData()
|
2023-11-06 08:29:33 +01:00
|
|
|
{
|
|
|
|
|
// This test check if storage shadowing works OK.
|
|
|
|
|
|
2023-11-19 14:50:55 +01:00
|
|
|
const Storage<CustomStorage> storage;
|
2023-11-06 08:29:33 +01:00
|
|
|
// This helper storage collect the pointers to storages created by shadowedStorage.
|
2023-11-19 14:50:55 +01:00
|
|
|
const Storage<QHash<int, int *>> helperStorage; // One instance in this test.
|
2023-11-06 08:29:33 +01:00
|
|
|
// This storage is repeated in nested groups, the innermost storage will shadow outer ones.
|
2023-11-19 14:50:55 +01:00
|
|
|
const Storage<int> shadowedStorage; // Three instances in this test.
|
2023-11-06 08:29:33 +01:00
|
|
|
|
|
|
|
|
const auto groupSetupWithStorage = [storage, helperStorage, shadowedStorage](int taskId) {
|
|
|
|
|
return onGroupSetup([storage, helperStorage, shadowedStorage, taskId] {
|
|
|
|
|
storage->m_log.append({taskId, Handler::GroupSetup});
|
|
|
|
|
helperStorage->insert(taskId, shadowedStorage.activeStorage());
|
|
|
|
|
*shadowedStorage = taskId;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
const auto groupDoneWithStorage = [storage, helperStorage, shadowedStorage](int taskId) {
|
|
|
|
|
return onGroupDone([storage, helperStorage, shadowedStorage, taskId](DoneWith result) {
|
|
|
|
|
storage->m_log.append({taskId, resultToGroupHandler(result)});
|
|
|
|
|
auto it = helperStorage->find(taskId);
|
|
|
|
|
if (it == helperStorage->end()) {
|
|
|
|
|
qWarning() << "The helperStorage is missing the shadowedStorage.";
|
|
|
|
|
return;
|
|
|
|
|
} else if (*it != shadowedStorage.activeStorage()) {
|
|
|
|
|
qWarning() << "Wrong active instance of the shadowedStorage.";
|
|
|
|
|
return;
|
|
|
|
|
} else if (**it != taskId) {
|
|
|
|
|
qWarning() << "Wrong data of the active instance of the shadowedStorage.";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
helperStorage->erase(it);
|
|
|
|
|
storage->m_log.append({*shadowedStorage, Handler::Storage});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
helperStorage,
|
|
|
|
|
shadowedStorage,
|
2023-11-06 08:29:33 +01:00
|
|
|
groupSetupWithStorage(1),
|
|
|
|
|
Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
shadowedStorage,
|
2023-11-06 08:29:33 +01:00
|
|
|
groupSetupWithStorage(2),
|
|
|
|
|
Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
shadowedStorage,
|
2023-11-06 08:29:33 +01:00
|
|
|
groupSetupWithStorage(3),
|
|
|
|
|
groupDoneWithStorage(3)
|
|
|
|
|
},
|
|
|
|
|
Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
shadowedStorage,
|
2023-11-06 08:29:33 +01:00
|
|
|
groupSetupWithStorage(4),
|
|
|
|
|
groupDoneWithStorage(4)
|
|
|
|
|
},
|
|
|
|
|
groupDoneWithStorage(2)
|
|
|
|
|
},
|
|
|
|
|
groupDoneWithStorage(1)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSuccess},
|
|
|
|
|
{3, Handler::Storage},
|
|
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::GroupSuccess},
|
|
|
|
|
{4, Handler::Storage},
|
|
|
|
|
{2, Handler::GroupSuccess},
|
|
|
|
|
{2, Handler::Storage},
|
|
|
|
|
{1, Handler::GroupSuccess},
|
|
|
|
|
{1, Handler::Storage},
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-06 20:08:42 +01:00
|
|
|
return {storage, root, log, 0, DoneWith::Success};
|
2023-11-06 08:29:33 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-13 13:01:55 +01:00
|
|
|
static TestData parallelData()
|
|
|
|
|
{
|
2023-11-19 14:50:55 +01:00
|
|
|
Storage<CustomStorage> storage;
|
2023-11-13 13:01:55 +01:00
|
|
|
|
|
|
|
|
const auto setupTask = [storage](int taskId, milliseconds timeout) {
|
|
|
|
|
return [storage, taskId, timeout](TaskObject &taskObject) {
|
|
|
|
|
taskObject = timeout;
|
|
|
|
|
storage->m_log.append({taskId, Handler::Setup});
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto setupDone = [storage](int taskId, DoneResult result = DoneResult::Success) {
|
|
|
|
|
return [storage, taskId, result](DoneWith doneWith) {
|
|
|
|
|
const Handler handler = doneWith == DoneWith::Cancel ? Handler::Canceled
|
|
|
|
|
: result == DoneResult::Success ? Handler::Success : Handler::Error;
|
|
|
|
|
storage->m_log.append({taskId, handler});
|
|
|
|
|
return doneWith == DoneWith::Cancel ? DoneResult::Error
|
|
|
|
|
: result == DoneResult::Success ? DoneResult::Success : DoneResult::Error;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto createTask = [storage, setupTask, setupDone](
|
|
|
|
|
int taskId, DoneResult result, milliseconds timeout = 0ms) {
|
|
|
|
|
return TestTask(setupTask(taskId, timeout), setupDone(taskId, result));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto createSuccessTask = [createTask](int taskId, milliseconds timeout = 0ms) {
|
|
|
|
|
return createTask(taskId, DoneResult::Success, timeout);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto groupDone = [storage](int taskId) {
|
|
|
|
|
return onGroupDone([storage, taskId](DoneWith result) {
|
|
|
|
|
storage->m_log.append({taskId, resultToGroupHandler(result)});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-13 13:01:55 +01:00
|
|
|
parallel,
|
|
|
|
|
createSuccessTask(1),
|
|
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSuccessTask(3),
|
|
|
|
|
createSuccessTask(4),
|
|
|
|
|
createSuccessTask(5),
|
|
|
|
|
groupDone(0)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{3, Handler::Success},
|
|
|
|
|
{4, Handler::Success},
|
|
|
|
|
{5, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {storage, root, log, 5, DoneWith::Success};
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-10 21:38:41 +02:00
|
|
|
void tst_Tasking::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
|
|
|
|
2023-11-19 14:50:55 +01:00
|
|
|
Storage<CustomStorage> storage;
|
2022-12-05 18:08:48 +01:00
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const auto setupTask = [storage](int taskId, milliseconds timeout) {
|
|
|
|
|
return [storage, taskId, timeout](TaskObject &taskObject) {
|
|
|
|
|
taskObject = timeout;
|
|
|
|
|
storage->m_log.append({taskId, Handler::Setup});
|
|
|
|
|
};
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
|
2023-11-06 18:52:19 +01:00
|
|
|
const auto setupTaskWithTweak = [storage](int taskId, SetupResult result) {
|
|
|
|
|
return [storage, taskId, result](TaskObject &) {
|
2023-05-27 17:20:40 +02:00
|
|
|
storage->m_log.append({taskId, Handler::Setup});
|
2023-11-06 18:52:19 +01:00
|
|
|
storage->m_log.append({taskId, toTweakSetupHandler(result)});
|
|
|
|
|
return result;
|
2023-05-27 17:20:40 +02:00
|
|
|
};
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
|
2023-11-06 18:52:19 +01:00
|
|
|
const auto setupDone = [storage](int taskId, DoneResult result = DoneResult::Success) {
|
|
|
|
|
return [storage, taskId, result](DoneWith doneWith) {
|
|
|
|
|
const Handler handler = doneWith == DoneWith::Cancel ? Handler::Canceled
|
|
|
|
|
: result == DoneResult::Success ? Handler::Success : Handler::Error;
|
2023-11-03 10:36:11 +01:00
|
|
|
storage->m_log.append({taskId, handler});
|
2023-11-06 18:52:19 +01:00
|
|
|
return doneWith == DoneWith::Cancel ? DoneResult::Error
|
|
|
|
|
: result == DoneResult::Success ? DoneResult::Success : DoneResult::Error;
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
|
2023-05-29 00:13:12 +02:00
|
|
|
const auto setupTimeout = [storage](int taskId) {
|
|
|
|
|
return [storage, taskId] {
|
|
|
|
|
storage->m_log.append({taskId, Handler::Timeout});
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-10-31 17:03:48 +01:00
|
|
|
const auto createTask = [storage, setupTask, setupDone](
|
2023-11-06 18:52:19 +01:00
|
|
|
int taskId, DoneResult result, milliseconds timeout = 0ms) {
|
|
|
|
|
return TestTask(setupTask(taskId, timeout), setupDone(taskId, result));
|
2023-05-27 17:20:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto createSuccessTask = [createTask](int taskId, milliseconds timeout = 0ms) {
|
2023-11-06 18:52:19 +01:00
|
|
|
return createTask(taskId, DoneResult::Success, timeout);
|
2023-05-27 17:20:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto createFailingTask = [createTask](int taskId, milliseconds timeout = 0ms) {
|
2023-11-06 18:52:19 +01:00
|
|
|
return createTask(taskId, DoneResult::Error, timeout);
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
|
2023-11-04 21:46:10 +01:00
|
|
|
const auto createTaskWithSetupTweak = [storage, setupTaskWithTweak, setupDone](
|
|
|
|
|
int taskId, SetupResult desiredResult) {
|
|
|
|
|
return TestTask(setupTaskWithTweak(taskId, desiredResult), setupDone(taskId));
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
|
2023-04-28 14:41:02 +02:00
|
|
|
const auto groupSetup = [storage](int taskId) {
|
2023-11-03 18:50:32 +01:00
|
|
|
return onGroupSetup([storage, taskId] {
|
|
|
|
|
storage->m_log.append({taskId, Handler::GroupSetup});
|
|
|
|
|
});
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2024-01-24 12:11:17 +01:00
|
|
|
const auto groupDone = [storage](int taskId, CallDoneIf callIf = CallDoneIf::SuccessOrError) {
|
2023-11-03 18:50:32 +01:00
|
|
|
return onGroupDone([storage, taskId](DoneWith result) {
|
|
|
|
|
storage->m_log.append({taskId, resultToGroupHandler(result)});
|
2024-01-24 12:11:17 +01:00
|
|
|
}, callIf);
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-11-04 21:46:10 +01:00
|
|
|
const auto groupSetupWithTweak = [storage](int taskId, SetupResult desiredResult) {
|
|
|
|
|
return onGroupSetup([storage, taskId, desiredResult] {
|
|
|
|
|
storage->m_log.append({taskId, Handler::GroupSetup});
|
2023-11-06 18:52:19 +01:00
|
|
|
storage->m_log.append({taskId, toTweakSetupHandler(desiredResult)});
|
2023-11-04 21:46:10 +01:00
|
|
|
return desiredResult;
|
|
|
|
|
});
|
|
|
|
|
};
|
2023-11-06 19:17:28 +01:00
|
|
|
const auto groupDoneWithTweak = [storage](int taskId, DoneResult result) {
|
|
|
|
|
return onGroupDone([storage, taskId, result](DoneWith doneWith) {
|
|
|
|
|
storage->m_log.append({taskId, resultToGroupHandler(doneWith)});
|
|
|
|
|
storage->m_log.append({taskId, toTweakDoneHandler(result)});
|
|
|
|
|
return result;
|
2023-11-04 21:46:10 +01:00
|
|
|
});
|
|
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
const auto createSync = [storage](int taskId) {
|
2023-11-04 21:46:10 +01:00
|
|
|
return Sync([storage, taskId] { storage->m_log.append({taskId, Handler::Sync}); });
|
2023-04-26 12:33:11 +02:00
|
|
|
};
|
2023-11-06 17:48:56 +01:00
|
|
|
const auto createSyncWithTweak = [storage](int taskId, DoneResult result) {
|
|
|
|
|
return Sync([storage, taskId, result] {
|
2023-11-04 21:46:10 +01:00
|
|
|
storage->m_log.append({taskId, Handler::Sync});
|
2023-11-06 18:52:19 +01:00
|
|
|
storage->m_log.append({taskId, toTweakDoneHandler(result)});
|
2023-11-06 17:48:56 +01:00
|
|
|
return result;
|
2023-11-04 21:46:10 +01:00
|
|
|
});
|
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 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-01-31 19:33:22 +01:00
|
|
|
};
|
|
|
|
|
const Group root2 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-06-16 21:33:59 +02:00
|
|
|
onGroupSetup([] { return SetupResult::Continue; }),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-01-31 19:33:22 +01:00
|
|
|
};
|
|
|
|
|
const Group root3 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 12:57:23 +01:00
|
|
|
onGroupSetup([] { return SetupResult::StopWithSuccess; }),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-01-31 19:33:22 +01:00
|
|
|
};
|
|
|
|
|
const Group root4 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-06-16 21:33:59 +02:00
|
|
|
onGroupSetup([] { return SetupResult::StopWithError; }),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-06-16 16:37:50 +02:00
|
|
|
|
2023-11-03 10:36:11 +01:00
|
|
|
const Log logDone {{0, Handler::GroupSuccess}};
|
2023-01-31 19:33:22 +01:00
|
|
|
const Log logError {{0, Handler::GroupError}};
|
2023-06-16 16:37:50 +02:00
|
|
|
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("Empty") << TestData{storage, root1, logDone, 0, DoneWith::Success};
|
|
|
|
|
QTest::newRow("EmptyContinue") << TestData{storage, root2, logDone, 0, DoneWith::Success};
|
|
|
|
|
QTest::newRow("EmptyDone") << TestData{storage, root3, logDone, 0, DoneWith::Success};
|
|
|
|
|
QTest::newRow("EmptyError") << TestData{storage, root4, logError, 0, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-06-16 16:37:50 +02:00
|
|
|
{
|
2023-06-16 21:33:59 +02:00
|
|
|
const auto setupGroup = [=](SetupResult setupResult, WorkflowPolicy policy) {
|
2023-06-16 16:37:50 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-06-16 16:37:50 +02:00
|
|
|
workflowPolicy(policy),
|
2023-06-16 21:33:59 +02:00
|
|
|
onGroupSetup([setupResult] { return setupResult; }),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-06-16 16:37:50 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto doneData = [storage, setupGroup](WorkflowPolicy policy) {
|
2023-11-04 12:57:23 +01:00
|
|
|
return TestData{storage, setupGroup(SetupResult::StopWithSuccess, policy),
|
2023-11-06 20:08:42 +01:00
|
|
|
Log{{0, Handler::GroupSuccess}}, 0, DoneWith::Success};
|
2023-06-16 16:37:50 +02:00
|
|
|
};
|
|
|
|
|
const auto errorData = [storage, setupGroup](WorkflowPolicy policy) {
|
2023-06-16 21:33:59 +02:00
|
|
|
return TestData{storage, setupGroup(SetupResult::StopWithError, policy),
|
2023-11-06 20:08:42 +01:00
|
|
|
Log{{0, Handler::GroupError}}, 0, DoneWith::Error};
|
2023-06-16 16:37:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QTest::newRow("DoneAndStopOnError") << doneData(WorkflowPolicy::StopOnError);
|
|
|
|
|
QTest::newRow("DoneAndContinueOnError") << doneData(WorkflowPolicy::ContinueOnError);
|
2023-11-04 12:44:19 +01:00
|
|
|
QTest::newRow("DoneAndStopOnSuccess") << doneData(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("DoneAndContinueOnSuccess") << doneData(WorkflowPolicy::ContinueOnSuccess);
|
2023-11-08 13:52:27 +01:00
|
|
|
QTest::newRow("DoneAndStopOnSuccessOrError") << doneData(WorkflowPolicy::StopOnSuccessOrError);
|
2023-11-04 12:44:19 +01:00
|
|
|
QTest::newRow("DoneAndFinishAllAndSuccess") << doneData(WorkflowPolicy::FinishAllAndSuccess);
|
2023-06-16 16:37:50 +02:00
|
|
|
QTest::newRow("DoneAndFinishAllAndError") << doneData(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
|
|
|
|
|
QTest::newRow("ErrorAndStopOnError") << errorData(WorkflowPolicy::StopOnError);
|
|
|
|
|
QTest::newRow("ErrorAndContinueOnError") << errorData(WorkflowPolicy::ContinueOnError);
|
2023-11-04 12:44:19 +01:00
|
|
|
QTest::newRow("ErrorAndStopOnSuccess") << errorData(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("ErrorAndContinueOnSuccess") << errorData(WorkflowPolicy::ContinueOnSuccess);
|
2023-11-08 13:52:27 +01:00
|
|
|
QTest::newRow("ErrorAndStopOnSuccessOrError") << errorData(WorkflowPolicy::StopOnSuccessOrError);
|
2023-11-04 12:44:19 +01:00
|
|
|
QTest::newRow("ErrorAndFinishAllAndSuccess") << errorData(WorkflowPolicy::FinishAllAndSuccess);
|
2023-06-16 16:37:50 +02:00
|
|
|
QTest::newRow("ErrorAndFinishAllAndError") << errorData(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(1, SetupResult::StopWithSuccess),
|
|
|
|
|
createTaskWithSetupTweak(2, SetupResult::StopWithSuccess)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-04 21:46:10 +01:00
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::TweakSetupToSuccess},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::TweakSetupToSuccess}
|
|
|
|
|
};
|
2024-01-09 22:52:05 +01:00
|
|
|
QTest::newRow("TweakTaskSuccess") << TestData{storage, root, log, 2, DoneWith::Success};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(1, SetupResult::StopWithError),
|
|
|
|
|
createTaskWithSetupTweak(2, SetupResult::StopWithError)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-04 21:46:10 +01:00
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::TweakSetupToError}
|
|
|
|
|
};
|
2024-01-09 22:52:05 +01:00
|
|
|
QTest::newRow("TweakTaskError") << TestData{storage, root, log, 2, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(1, SetupResult::Continue),
|
|
|
|
|
createTaskWithSetupTweak(2, SetupResult::Continue),
|
|
|
|
|
createTaskWithSetupTweak(3, SetupResult::StopWithError),
|
|
|
|
|
createTaskWithSetupTweak(4, SetupResult::Continue)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::TweakSetupToContinue},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{2, Handler::TweakSetupToContinue},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::TweakSetupToError}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2024-01-09 22:52:05 +01:00
|
|
|
QTest::newRow("TweakMixed") << TestData{storage, root, log, 4, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
parallel,
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(1, SetupResult::Continue),
|
|
|
|
|
createTaskWithSetupTweak(2, SetupResult::Continue),
|
|
|
|
|
createTaskWithSetupTweak(3, SetupResult::StopWithError),
|
|
|
|
|
createTaskWithSetupTweak(4, SetupResult::Continue)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::TweakSetupToContinue},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{2, Handler::TweakSetupToContinue},
|
2023-01-26 19:06:02 +01:00
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled},
|
|
|
|
|
{2, Handler::Canceled}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2024-01-09 22:52:05 +01:00
|
|
|
QTest::newRow("TweakParallel") << TestData{storage, root, log, 4, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
parallel,
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(1, SetupResult::Continue),
|
|
|
|
|
createTaskWithSetupTweak(2, SetupResult::Continue),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(3, SetupResult::StopWithError)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(4, SetupResult::Continue)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::TweakSetupToContinue},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{2, Handler::TweakSetupToContinue},
|
2023-01-26 19:06:02 +01:00
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled},
|
|
|
|
|
{2, Handler::Canceled}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2024-01-09 22:52:05 +01:00
|
|
|
QTest::newRow("TweakParallelGroup") << TestData{storage, root, log, 4, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
parallel,
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(1, SetupResult::Continue),
|
|
|
|
|
createTaskWithSetupTweak(2, SetupResult::Continue),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
2023-11-04 21:46:10 +01:00
|
|
|
groupSetupWithTweak(0, SetupResult::StopWithError),
|
|
|
|
|
createTaskWithSetupTweak(3, SetupResult::Continue)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(4, SetupResult::Continue)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::TweakSetupToContinue},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{2, Handler::TweakSetupToContinue},
|
2023-01-26 19:06:02 +01:00
|
|
|
{0, Handler::GroupSetup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{0, Handler::TweakSetupToError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled},
|
|
|
|
|
{2, Handler::Canceled}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2024-01-09 22:52:05 +01:00
|
|
|
QTest::newRow("TweakParallelGroupSetup")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root, log, 4, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
|
|
|
|
Group {
|
|
|
|
|
Group {
|
|
|
|
|
Group {
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(5),
|
|
|
|
|
groupSetup(5),
|
|
|
|
|
groupDone(5)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
groupDone(4)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
|
|
|
|
groupDone(3)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
|
|
|
|
groupDone(2)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
|
|
|
|
groupDone(1)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupDone(0)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{5, Handler::GroupSetup},
|
|
|
|
|
{5, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{5, Handler::Success},
|
|
|
|
|
{5, Handler::GroupSuccess},
|
|
|
|
|
{4, Handler::GroupSuccess},
|
|
|
|
|
{3, Handler::GroupSuccess},
|
|
|
|
|
{2, Handler::GroupSuccess},
|
|
|
|
|
{1, Handler::GroupSuccess},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("Nested") << TestData{storage, root, log, 1, DoneWith::Success};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-13 13:01:55 +01:00
|
|
|
QTest::newRow("Parallel") << parallelData();
|
2023-01-26 19:06:02 +01:00
|
|
|
|
|
|
|
|
{
|
2023-05-27 17:20:40 +02:00
|
|
|
auto setupSubTree = [storage, createSuccessTask](TaskTree &taskTree) {
|
2023-01-26 19:06:02 +01:00
|
|
|
const Group nestedRoot {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSuccessTask(3),
|
|
|
|
|
createSuccessTask(4)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-06-06 11:37:27 +02:00
|
|
|
taskTree.setRecipe(nestedRoot);
|
2023-01-26 19:06:02 +01:00
|
|
|
CustomStorage *activeStorage = storage.activeStorage();
|
2023-08-31 19:25:59 +02:00
|
|
|
const auto collectSubLog = [activeStorage](const CustomStorage &subTreeStorage){
|
2023-08-31 18:31:34 +02:00
|
|
|
activeStorage->m_log += subTreeStorage.m_log;
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
taskTree.onStorageDone(storage, collectSubLog);
|
|
|
|
|
};
|
|
|
|
|
const Group root1 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(1),
|
|
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSuccessTask(3),
|
|
|
|
|
createSuccessTask(4),
|
|
|
|
|
createSuccessTask(5),
|
|
|
|
|
groupDone(0)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Group root2 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
Group { createSuccessTask(1) },
|
|
|
|
|
Group { createSuccessTask(2) },
|
|
|
|
|
Group { createSuccessTask(3) },
|
|
|
|
|
Group { createSuccessTask(4) },
|
|
|
|
|
Group { createSuccessTask(5) },
|
|
|
|
|
groupDone(0)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Group root3 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(1),
|
2023-05-09 23:43:18 +02:00
|
|
|
TaskTreeTask(setupSubTree),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(5),
|
|
|
|
|
groupDone(0)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{5, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{5, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("Sequential") << TestData{storage, root1, log, 5, DoneWith::Success};
|
|
|
|
|
QTest::newRow("SequentialEncapsulated") << TestData{storage, root2, log, 5, DoneWith::Success};
|
2023-05-16 23:21:55 +02:00
|
|
|
// We don't inspect subtrees, so taskCount is 3, not 5.
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SequentialSubTree") << TestData{storage, root3, log, 3, DoneWith::Success};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(1),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(2),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(3),
|
2022-10-12 14:30:24 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(4),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(5),
|
|
|
|
|
groupDone(5)
|
2023-01-26 19:06:02 +01:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupDone(4)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupDone(3)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupDone(2)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupDone(1)
|
2022-10-12 14:30:24 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
groupDone(0)
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{5, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{5, Handler::Success},
|
|
|
|
|
{5, Handler::GroupSuccess},
|
|
|
|
|
{4, Handler::GroupSuccess},
|
|
|
|
|
{3, Handler::GroupSuccess},
|
|
|
|
|
{2, Handler::GroupSuccess},
|
|
|
|
|
{1, Handler::GroupSuccess},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SequentialNested") << TestData{storage, root, log, 5, DoneWith::Success};
|
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 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(1),
|
|
|
|
|
createSuccessTask(2),
|
|
|
|
|
createFailingTask(3),
|
|
|
|
|
createSuccessTask(4),
|
|
|
|
|
createSuccessTask(5),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2022-10-12 14:30:24 +02:00
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{3, Handler::Error},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SequentialError") << TestData{storage, root, log, 5, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-05-19 19:31:22 +02:00
|
|
|
{
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, groupDone](WorkflowPolicy policy) {
|
2023-05-19 19:31:22 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-19 19:31:22 +02:00
|
|
|
workflowPolicy(policy),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-19 19:31:22 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-03 10:36:11 +01:00
|
|
|
const Log doneLog = {{0, Handler::GroupSuccess}};
|
2023-05-28 22:07:17 +02:00
|
|
|
const Log errorLog = {{0, Handler::GroupError}};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
2023-05-28 22:07:17 +02:00
|
|
|
QTest::newRow("EmptyStopOnError") << TestData{storage, root1, doneLog, 0,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
2023-05-28 22:07:17 +02:00
|
|
|
QTest::newRow("EmptyContinueOnError") << TestData{storage, root2, doneLog, 0,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("EmptyStopOnSuccess") << TestData{storage, root3, errorLog, 0,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("EmptyContinueOnSuccess") << TestData{storage, root4, errorLog, 0,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("EmptyStopOnSuccessOrError") << TestData{storage, root5, errorLog, 0,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("EmptyFinishAllAndSuccess") << TestData{storage, root6, doneLog, 0,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("EmptyFinishAllAndError") << TestData{storage, root7, errorLog, 0,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createSuccessTask, groupDone](
|
2023-05-27 17:20:40 +02:00
|
|
|
WorkflowPolicy policy) {
|
2023-05-19 19:31:22 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-19 19:31:22 +02:00
|
|
|
workflowPolicy(policy),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(1),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-19 19:31:22 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-05-28 22:07:17 +02:00
|
|
|
const Log doneLog = {
|
2023-05-19 19:31:22 +02:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-05-19 19:31:22 +02:00
|
|
|
};
|
|
|
|
|
|
2023-05-28 22:07:17 +02:00
|
|
|
const Log errorLog = {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-05-28 22:07:17 +02:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
2023-05-28 22:07:17 +02:00
|
|
|
QTest::newRow("DoneStopOnError") << TestData{storage, root1, doneLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
2023-05-28 22:07:17 +02:00
|
|
|
QTest::newRow("DoneContinueOnError") << TestData{storage, root2, doneLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("DoneStopOnSuccess") << TestData{storage, root3, doneLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("DoneContinueOnSuccess") << TestData{storage, root4, doneLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("DoneStopOnSuccessOrError") << TestData{storage, root5, doneLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("DoneFinishAllAndSuccess") << TestData{storage, root6, doneLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("DoneFinishAllAndError") << TestData{storage, root7, errorLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createFailingTask, groupDone](
|
2023-05-27 17:20:40 +02:00
|
|
|
WorkflowPolicy policy) {
|
2023-05-19 19:31:22 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-19 19:31:22 +02:00
|
|
|
workflowPolicy(policy),
|
2023-05-27 17:20:40 +02:00
|
|
|
createFailingTask(1),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-19 19:31:22 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-05-28 22:07:17 +02:00
|
|
|
const Log doneLog = {
|
2023-05-19 19:31:22 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{0, Handler::GroupSuccess}
|
2023-05-19 19:31:22 +02:00
|
|
|
};
|
|
|
|
|
|
2023-05-28 22:07:17 +02:00
|
|
|
const Log errorLog = {
|
2023-05-19 19:31:22 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
2023-05-28 22:07:17 +02:00
|
|
|
{0, Handler::GroupError}
|
2023-05-19 19:31:22 +02:00
|
|
|
};
|
|
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
2023-05-28 22:07:17 +02:00
|
|
|
QTest::newRow("ErrorStopOnError") << TestData{storage, root1, errorLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
2023-05-28 22:07:17 +02:00
|
|
|
QTest::newRow("ErrorContinueOnError") << TestData{storage, root2, errorLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("ErrorStopOnSuccess") << TestData{storage, root3, errorLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("ErrorContinueOnSuccess") << TestData{storage, root4, errorLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("ErrorStopOnSuccessOrError") << TestData{storage, root5, errorLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("ErrorFinishAllAndSuccess") << TestData{storage, root6, doneLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("ErrorFinishAllAndError") << TestData{storage, root7, errorLog, 1,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-19 19:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-28 12:42:05 +02:00
|
|
|
{
|
|
|
|
|
// These tests check whether the proper root's group end handler is called
|
|
|
|
|
// when the group is stopped. Test it with different workflow policies.
|
|
|
|
|
// The root starts one short failing task together with one long task.
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone](
|
|
|
|
|
WorkflowPolicy policy) {
|
2023-05-28 12:42:05 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-28 12:42:05 +02:00
|
|
|
parallel,
|
|
|
|
|
workflowPolicy(policy),
|
|
|
|
|
createFailingTask(1, 1ms),
|
2023-05-31 18:29:11 +02:00
|
|
|
createSuccessTask(2, 1ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log errorErrorLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Canceled},
|
2023-05-28 12:42:05 +02:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log errorDoneLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-05-28 12:42:05 +02:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log doneLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
|
|
|
|
QTest::newRow("StopRootWithStopOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, errorErrorLog, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
|
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
|
|
|
|
QTest::newRow("StopRootWithContinueOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, errorDoneLog, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("StopRootWithStopOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, doneLog, 2, DoneWith::Success};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("StopRootWithContinueOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, doneLog, 2, DoneWith::Success};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("StopRootWithStopOnSuccessOrError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root5, errorErrorLog, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("StopRootWithFinishAllAndSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root6, doneLog, 2, DoneWith::Success};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("StopRootWithFinishAllAndError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root7, errorDoneLog, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// These tests check whether the proper root's group end handler is called
|
|
|
|
|
// when the group is stopped. Test it with different workflow policies.
|
|
|
|
|
// The root starts in parallel: one very short successful task, one short failing task
|
|
|
|
|
// and one long task.
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone](
|
|
|
|
|
WorkflowPolicy policy) {
|
2023-05-28 12:42:05 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-28 12:42:05 +02:00
|
|
|
parallel,
|
|
|
|
|
workflowPolicy(policy),
|
|
|
|
|
createSuccessTask(1),
|
|
|
|
|
createFailingTask(2, 1ms),
|
2023-05-31 18:29:11 +02:00
|
|
|
createSuccessTask(3, 1ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log errorErrorLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Canceled},
|
2023-05-28 12:42:05 +02:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log errorDoneLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
2023-05-28 12:42:05 +02:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log doneErrorLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Canceled},
|
|
|
|
|
{3, Handler::Canceled},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log doneDoneLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
|
|
|
|
QTest::newRow("StopRootAfterDoneWithStopOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, errorErrorLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
|
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
|
|
|
|
QTest::newRow("StopRootAfterDoneWithContinueOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, errorDoneLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("StopRootAfterDoneWithStopOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, doneErrorLog, 3, DoneWith::Success};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("StopRootAfterDoneWithContinueOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, doneDoneLog, 3, DoneWith::Success};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("StopRootAfterDoneWithStopOnSuccessOrError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root5, doneErrorLog, 3, DoneWith::Success};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("StopRootAfterDoneWithFinishAllAndSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root6, doneDoneLog, 3, DoneWith::Success};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("StopRootAfterDoneWithFinishAllAndError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root7, errorDoneLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// These tests check whether the proper subgroup's end handler is called
|
|
|
|
|
// when the group is stopped. Test it with different workflow policies.
|
|
|
|
|
// The subgroup starts one long task.
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone](
|
|
|
|
|
WorkflowPolicy policy) {
|
2023-05-28 12:42:05 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-28 12:42:05 +02:00
|
|
|
parallel,
|
|
|
|
|
Group {
|
|
|
|
|
workflowPolicy(policy),
|
|
|
|
|
createSuccessTask(1, 1000ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(1)
|
2023-05-28 12:42:05 +02:00
|
|
|
},
|
|
|
|
|
createFailingTask(2, 1ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(2)
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
const Log log = {
|
2023-05-28 12:42:05 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled},
|
2023-11-04 09:44:33 +01:00
|
|
|
{1, Handler::GroupCanceled},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
|
|
|
|
QTest::newRow("StopGroupWithStopOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, log, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
|
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
|
|
|
|
QTest::newRow("StopGroupWithContinueOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, log, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("StopGroupWithStopOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, log, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("StopGroupWithContinueOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, log, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("StopGroupWithStopOnSuccessOrError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root5, log, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
// TODO: Behavioral change! Fix Docs!
|
2023-11-04 12:44:19 +01:00
|
|
|
// Cancellation always invokes error handler (i.e. DoneWith is Canceled)
|
|
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("StopGroupWithFinishAllAndSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root6, log, 2, DoneWith::Error};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("StopGroupWithFinishAllAndError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root7, log, 2, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// These tests check whether the proper subgroup's end handler is called
|
|
|
|
|
// when the group is stopped. Test it with different workflow policies.
|
|
|
|
|
// The sequential subgroup starts one short successful task followed by one long task.
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone](
|
|
|
|
|
WorkflowPolicy policy) {
|
2023-05-28 12:42:05 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-28 12:42:05 +02:00
|
|
|
parallel,
|
|
|
|
|
Group {
|
|
|
|
|
workflowPolicy(policy),
|
|
|
|
|
createSuccessTask(1),
|
|
|
|
|
createSuccessTask(2, 1000ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(1)
|
2023-05-28 12:42:05 +02:00
|
|
|
},
|
|
|
|
|
createFailingTask(3, 1ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(2)
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log errorLog = {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Canceled},
|
2023-11-04 09:44:33 +01:00
|
|
|
{1, Handler::GroupCanceled},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
const Log doneLog = {
|
2023-05-28 12:42:05 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
|
|
|
|
{1, Handler::GroupSuccess},
|
2023-05-28 12:42:05 +02:00
|
|
|
{3, Handler::Error},
|
|
|
|
|
{2, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
|
|
|
|
QTest::newRow("StopGroupAfterDoneWithStopOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, errorLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
|
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
|
|
|
|
QTest::newRow("StopGroupAfterDoneWithContinueOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, errorLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("StopGroupAfterDoneWithStopOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, doneLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
// TODO: Behavioral change!
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("StopGroupAfterDoneWithContinueOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, errorLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("StopGroupAfterDoneWithStopOnSuccessOrError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root5, doneLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
// TODO: Behavioral change!
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("StopGroupAfterDoneWithFinishAllAndSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root6, errorLog, 3, DoneWith::Error};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("StopGroupAfterDoneWithFinishAllAndError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root7, errorLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// These tests check whether the proper subgroup's end handler is called
|
|
|
|
|
// when the group is stopped. Test it with different workflow policies.
|
|
|
|
|
// The sequential subgroup starts one short failing task followed by one long task.
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone](
|
|
|
|
|
WorkflowPolicy policy) {
|
2023-05-28 12:42:05 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-28 12:42:05 +02:00
|
|
|
parallel,
|
|
|
|
|
Group {
|
|
|
|
|
workflowPolicy(policy),
|
|
|
|
|
createFailingTask(1),
|
|
|
|
|
createSuccessTask(2, 1000ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(1)
|
2023-05-28 12:42:05 +02:00
|
|
|
},
|
|
|
|
|
createFailingTask(3, 1ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(2)
|
2023-05-28 12:42:05 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
const Log shortLog = {
|
2023-05-28 12:42:05 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{1, Handler::GroupError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Canceled},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
const Log longLog = {
|
2023-05-28 12:42:05 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{3, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{3, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Canceled},
|
2023-11-04 09:44:33 +01:00
|
|
|
{1, Handler::GroupCanceled},
|
2023-05-28 12:42:05 +02:00
|
|
|
{2, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
|
|
|
|
QTest::newRow("StopGroupAfterErrorWithStopOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, shortLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
|
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
|
|
|
|
QTest::newRow("StopGroupAfterErrorWithContinueOnError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, longLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
|
|
|
|
QTest::newRow("StopGroupAfterErrorWithStopOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, longLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
|
|
|
|
QTest::newRow("StopGroupAfterErrorWithContinueOnSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, longLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
|
|
|
|
QTest::newRow("StopGroupAfterErrorWithStopOnSuccessOrError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root5, shortLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
|
2023-11-03 18:50:32 +01:00
|
|
|
// TODO: Behavioral change!
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
|
|
|
|
QTest::newRow("StopGroupAfterErrorWithFinishAllAndSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root6, longLog, 3, DoneWith::Error};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
|
|
|
|
QTest::newRow("StopGroupAfterErrorWithFinishAllAndError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root7, longLog, 3, DoneWith::Error};
|
2023-05-28 12:42:05 +02:00
|
|
|
}
|
|
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
2023-11-03 18:50:32 +01:00
|
|
|
const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone](
|
|
|
|
|
WorkflowPolicy policy) {
|
2023-05-27 17:20:40 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
workflowPolicy(policy),
|
|
|
|
|
createSuccessTask(1),
|
|
|
|
|
createFailingTask(2),
|
|
|
|
|
createSuccessTask(3),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-27 17:20:40 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(WorkflowPolicy::StopOnError);
|
|
|
|
|
const Log log1 {
|
2023-01-26 19:06:02 +01:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("StopOnError") << TestData{storage, root1, log1, 3, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
|
2023-05-27 17:20:40 +02:00
|
|
|
const Group root2 = createRoot(WorkflowPolicy::ContinueOnError);
|
2023-05-28 22:07:17 +02:00
|
|
|
const Log errorLog {
|
2023-01-26 19:06:02 +01:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("ContinueOnError") << TestData{storage, root2, errorLog, 3, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root3 = createRoot(WorkflowPolicy::StopOnSuccess);
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log3 {
|
2023-01-26 19:06:02 +01:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("StopOnSuccess") << TestData{storage, root3, log3, 3, DoneWith::Success};
|
2023-01-26 19:06:02 +01:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root4 = createRoot(WorkflowPolicy::ContinueOnSuccess);
|
2023-05-28 22:07:17 +02:00
|
|
|
const Log doneLog {
|
2023-01-26 19:06:02 +01:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("ContinueOnSuccess") << TestData{storage, root4, doneLog, 3, DoneWith::Success};
|
2023-01-26 19:06:02 +01:00
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
const Group root5 = createRoot(WorkflowPolicy::StopOnSuccessOrError);
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log5 {
|
2023-05-17 19:28:57 +02:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-05-17 19:28:57 +02:00
|
|
|
};
|
2023-11-08 13:52:27 +01:00
|
|
|
QTest::newRow("StopOnSuccessOrError") << TestData{storage, root5, log5, 3, DoneWith::Success};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
2023-11-04 12:44:19 +01:00
|
|
|
const Group root6 = createRoot(WorkflowPolicy::FinishAllAndSuccess);
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("FinishAllAndSuccess") << TestData{storage, root6, doneLog, 3, DoneWith::Success};
|
2023-05-28 22:07:17 +02:00
|
|
|
|
|
|
|
|
const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError);
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("FinishAllAndError") << TestData{storage, root7, errorLog, 3, DoneWith::Error};
|
2023-05-17 19:28:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2023-11-06 18:52:19 +01:00
|
|
|
const auto createRoot = [storage, createTask, groupDone](DoneResult firstResult,
|
|
|
|
|
DoneResult secondResult) {
|
2023-05-17 19:28:57 +02:00
|
|
|
return Group {
|
|
|
|
|
parallel,
|
2023-11-08 13:52:27 +01:00
|
|
|
stopOnSuccessOrError,
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-06 18:52:19 +01:00
|
|
|
createTask(1, firstResult, 1000ms),
|
|
|
|
|
createTask(2, secondResult, 1ms),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-17 19:28:57 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-06 18:52:19 +01:00
|
|
|
const Group root1 = createRoot(DoneResult::Success, DoneResult::Success);
|
|
|
|
|
const Group root2 = createRoot(DoneResult::Success, DoneResult::Error);
|
|
|
|
|
const Group root3 = createRoot(DoneResult::Error, DoneResult::Success);
|
|
|
|
|
const Group root4 = createRoot(DoneResult::Error, DoneResult::Error);
|
2023-05-17 19:28:57 +02:00
|
|
|
|
|
|
|
|
const Log success {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
|
|
|
|
{1, Handler::Canceled},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-05-17 19:28:57 +02:00
|
|
|
};
|
|
|
|
|
const Log failure {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled},
|
2023-05-17 19:28:57 +02:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-08 13:52:27 +01:00
|
|
|
QTest::newRow("StopOnSuccessOrError1")
|
|
|
|
|
<< TestData{storage, root1, success, 2, DoneWith::Success};
|
|
|
|
|
QTest::newRow("StopOnSuccessOrError2")
|
|
|
|
|
<< TestData{storage, root2, failure, 2, DoneWith::Error};
|
|
|
|
|
QTest::newRow("StopOnSuccessOrError3")
|
|
|
|
|
<< TestData{storage, root3, success, 2, DoneWith::Success};
|
|
|
|
|
QTest::newRow("StopOnSuccessOrError4")
|
|
|
|
|
<< TestData{storage, root4, failure, 2, DoneWith::Error};
|
2023-05-17 19:28:57 +02:00
|
|
|
}
|
|
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
2023-11-04 21:46:10 +01:00
|
|
|
// This test checks whether group setup handler's result is properly dispatched.
|
|
|
|
|
const auto createRoot = [storage, createSuccessTask, groupDone, groupSetupWithTweak](
|
|
|
|
|
SetupResult desiredResult) {
|
2023-05-27 17:20:40 +02:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
Group {
|
2023-11-04 21:46:10 +01:00
|
|
|
groupSetupWithTweak(1, desiredResult),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(1)
|
|
|
|
|
},
|
2023-11-04 21:46:10 +01:00
|
|
|
groupDone(0)
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(SetupResult::StopWithSuccess);
|
|
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::TweakSetupToSuccess},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupSetupTweakToSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, log1, 1, DoneWith::Success};
|
2023-11-04 21:46:10 +01:00
|
|
|
|
|
|
|
|
const Group root2 = createRoot(SetupResult::StopWithError);
|
|
|
|
|
const Log log2 {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::TweakSetupToError},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupSetupTweakToError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, log2, 1, DoneWith::Error};
|
2023-11-04 21:46:10 +01:00
|
|
|
|
|
|
|
|
const Group root3 = createRoot(SetupResult::Continue);
|
|
|
|
|
const Log log3 {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::TweakSetupToContinue},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupSetupTweakToContinue")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, log3, 1, DoneWith::Success};
|
2023-11-04 21:46:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// This test checks whether group done handler's result is properly dispatched.
|
|
|
|
|
const auto createRoot = [storage, createTask, groupDone, groupDoneWithTweak](
|
2023-11-06 19:17:28 +01:00
|
|
|
DoneResult firstResult, DoneResult secondResult) {
|
2023-11-04 21:46:10 +01:00
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
Group {
|
2023-11-06 18:52:19 +01:00
|
|
|
createTask(1, firstResult),
|
2023-11-06 19:17:28 +01:00
|
|
|
groupDoneWithTweak(1, secondResult)
|
2023-05-27 17:20:40 +02:00
|
|
|
},
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-05-27 17:20:40 +02:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-06 19:17:28 +01:00
|
|
|
const Group root1 = createRoot(DoneResult::Success, DoneResult::Success);
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log1 {
|
2023-01-26 19:06:02 +01:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::GroupSuccess},
|
|
|
|
|
{1, Handler::TweakDoneToSuccess},
|
2023-11-03 10:36:11 +01:00
|
|
|
{0, Handler::GroupSuccess}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-04 21:46:10 +01:00
|
|
|
QTest::newRow("GroupDoneWithSuccessTweakToSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, log1, 1, DoneWith::Success};
|
2023-01-26 19:06:02 +01:00
|
|
|
|
2023-11-06 19:17:28 +01:00
|
|
|
const Group root2 = createRoot(DoneResult::Success, DoneResult::Error);
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log2 {
|
2023-01-26 19:06:02 +01:00
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::GroupSuccess},
|
|
|
|
|
{1, Handler::TweakDoneToError},
|
2023-01-26 19:06:02 +01:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
2023-11-04 21:46:10 +01:00
|
|
|
QTest::newRow("GroupDoneWithSuccessTweakToError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, log2, 1, DoneWith::Error};
|
2023-11-04 21:46:10 +01:00
|
|
|
|
2023-11-06 19:17:28 +01:00
|
|
|
const Group root3 = createRoot(DoneResult::Error, DoneResult::Success);
|
2023-11-04 21:46:10 +01:00
|
|
|
const Log log3 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{1, Handler::GroupError},
|
|
|
|
|
{1, Handler::TweakDoneToSuccess},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupDoneWithErrorTweakToSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, log3, 1, DoneWith::Success};
|
2023-11-04 21:46:10 +01:00
|
|
|
|
2023-11-06 19:17:28 +01:00
|
|
|
const Group root4 = createRoot(DoneResult::Error, DoneResult::Error);
|
2023-11-04 21:46:10 +01:00
|
|
|
const Log log4 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{1, Handler::GroupError},
|
|
|
|
|
{1, Handler::TweakDoneToError},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupDoneWithErrorTweakToError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, log4, 1, DoneWith::Error};
|
2023-11-04 21:46:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// This test checks whether task setup handler's result is properly dispatched.
|
|
|
|
|
const auto createRoot = [storage, createSuccessTask, groupDone, createTaskWithSetupTweak](
|
|
|
|
|
SetupResult desiredResult) {
|
|
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-04 21:46:10 +01:00
|
|
|
Group {
|
|
|
|
|
createTaskWithSetupTweak(1, desiredResult),
|
|
|
|
|
createSuccessTask(2)
|
|
|
|
|
},
|
|
|
|
|
groupDone(0)
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root1 = createRoot(SetupResult::StopWithSuccess);
|
|
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::TweakSetupToSuccess},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("TaskSetupTweakToSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, log1, 2, DoneWith::Success};
|
2023-11-04 21:46:10 +01:00
|
|
|
|
|
|
|
|
const Group root2 = createRoot(SetupResult::StopWithError);
|
|
|
|
|
const Log log2 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::TweakSetupToError},
|
|
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("TaskSetupTweakToError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, log2, 2, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
|
2023-06-16 21:33:59 +02:00
|
|
|
const Group root3 = createRoot(SetupResult::Continue);
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log3 {
|
2023-01-26 19:06:02 +01:00
|
|
|
{1, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::TweakSetupToContinue},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-04 21:46:10 +01:00
|
|
|
QTest::newRow("TaskSetupTweakToContinue")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, log3, 2, DoneWith::Success};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-27 13:36:44 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-01-27 13:36:44 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
|
|
|
|
createSuccessTask(1)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
|
|
|
|
createSuccessTask(2)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
|
|
|
|
createSuccessTask(3)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
createSuccessTask(4)
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{4, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
|
|
|
|
{4, Handler::Success}
|
2023-01-27 13:36:44 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("NestedParallel") << TestData{storage, root, log, 4, DoneWith::Success};
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-01-27 13:36:44 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
|
|
|
|
createSuccessTask(1)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
|
|
|
|
createSuccessTask(2)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(3, SetupResult::StopWithSuccess)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
createSuccessTask(4)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(5),
|
|
|
|
|
createSuccessTask(5)
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToSuccess},
|
2023-01-27 13:36:44 +01:00
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{5, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{5, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success},
|
|
|
|
|
{5, Handler::Success}
|
2023-01-27 13:36:44 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("NestedParallelDone") << TestData{storage, root, log, 5, DoneWith::Success};
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2023-02-01 00:01:46 +01:00
|
|
|
const Group root1 {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-01-27 13:36:44 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
|
|
|
|
createSuccessTask(1)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
|
|
|
|
createSuccessTask(2)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(3, SetupResult::StopWithError)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
createSuccessTask(4)
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(5),
|
|
|
|
|
createSuccessTask(5)
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Canceled}
|
2023-05-27 17:20:40 +02: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
|
2023-05-17 19:28:57 +02:00
|
|
|
// - task 1 should be stopped as a consequence of the error inside the group
|
2023-04-28 14:41:02 +02:00
|
|
|
// - tasks 4 and 5 should be skipped
|
2023-02-01 00:01:46 +01:00
|
|
|
const Group root2 {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-02-01 00:01:46 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
2024-01-31 10:28:07 +01:00
|
|
|
createSuccessTask(1, 1s)
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
|
|
|
|
createSuccessTask(2)
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(3, SetupResult::StopWithError)
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
createSuccessTask(4)
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(5),
|
|
|
|
|
createSuccessTask(5)
|
2023-02-01 00:01:46 +01:00
|
|
|
}
|
|
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log2 {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled}
|
2023-05-27 17:20:40 +02:00
|
|
|
};
|
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,
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-02-01 00:01:46 +01:00
|
|
|
Group {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-02-01 00:01:46 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
2024-01-31 10:28:07 +01:00
|
|
|
createSuccessTask(1, 1s)
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2024-01-31 10:28:07 +01:00
|
|
|
createSuccessTask(2)
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-11-04 21:46:10 +01:00
|
|
|
createTaskWithSetupTweak(3, SetupResult::StopWithError)
|
2023-02-01 00:01:46 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
createSuccessTask(4)
|
2023-02-01 00:01:46 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(5),
|
|
|
|
|
createSuccessTask(5)
|
2023-02-01 00:01:46 +01:00
|
|
|
}
|
|
|
|
|
};
|
2023-05-27 17:20:40 +02:00
|
|
|
const Log log3 {
|
2023-01-27 13:36:44 +01:00
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{3, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled},
|
2023-05-27 17:20:40 +02:00
|
|
|
{5, Handler::GroupSetup},
|
|
|
|
|
{5, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{5, Handler::Success}
|
2023-01-27 13:36:44 +01:00
|
|
|
};
|
2023-02-01 00:01:46 +01:00
|
|
|
QTest::newRow("NestedParallelError1")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, log1, 5, DoneWith::Error};
|
2023-02-01 00:01:46 +01:00
|
|
|
QTest::newRow("NestedParallelError2")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, log2, 5, DoneWith::Error};
|
2023-02-01 00:01:46 +01:00
|
|
|
QTest::newRow("NestedParallelError3")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, log3, 5, DoneWith::Error};
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-26 19:06:02 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2022-11-04 14:08:32 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(1)
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2022-11-04 14:08:32 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(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-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(3)
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
|
|
|
|
},
|
2023-01-24 11:56:30 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
2023-01-26 19:06:02 +01:00
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(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},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-26 19:06:02 +01:00
|
|
|
{4, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
|
|
|
|
{4, Handler::Success}
|
2023-01-26 19:06:02 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("DeeplyNestedParallel") << TestData{storage, root, log, 4, DoneWith::Success};
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-01-27 13:36:44 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
|
|
|
|
Group { createSuccessTask(1) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
|
|
|
|
Group { createSuccessTask(2) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-11-04 21:46:10 +01:00
|
|
|
Group { createTaskWithSetupTweak(3, SetupResult::StopWithSuccess) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
Group { createSuccessTask(4) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(5),
|
|
|
|
|
Group { createSuccessTask(5) }
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToSuccess},
|
2023-01-27 13:36:44 +01:00
|
|
|
{4, Handler::GroupSetup},
|
|
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{5, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{5, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success},
|
|
|
|
|
{5, Handler::Success}
|
2023-01-27 13:36:44 +01:00
|
|
|
};
|
2023-11-04 21:46:10 +01:00
|
|
|
QTest::newRow("DeeplyNestedParallelSuccess")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root, log, 5, DoneWith::Success};
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-05-18 13:16:40 +02:00
|
|
|
parallelLimit(2),
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-01-27 13:36:44 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
|
|
|
|
Group { createSuccessTask(1) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
|
|
|
|
Group { createSuccessTask(2) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-11-04 21:46:10 +01:00
|
|
|
Group { createTaskWithSetupTweak(3, SetupResult::StopWithError) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(4),
|
|
|
|
|
Group { createSuccessTask(4) }
|
2023-01-27 13:36:44 +01:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(5),
|
|
|
|
|
Group { createSuccessTask(5) }
|
2023-01-27 13:36:44 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success},
|
2023-01-27 13:36:44 +01:00
|
|
|
{3, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::Setup},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakSetupToError},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Canceled}
|
2023-01-27 13:36:44 +01:00
|
|
|
};
|
|
|
|
|
QTest::newRow("DeeplyNestedParallelError")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root, log, 5, DoneWith::Error};
|
2023-01-26 19:06:02 +01:00
|
|
|
}
|
2023-02-06 20:27:59 +01:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSync(1),
|
|
|
|
|
createSync(2),
|
|
|
|
|
createSync(3),
|
|
|
|
|
createSync(4),
|
|
|
|
|
createSync(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}
|
|
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SyncSequential") << TestData{storage, root, log, 0, DoneWith::Success};
|
2023-02-06 20:27:59 +01:00
|
|
|
}
|
|
|
|
|
|
2023-04-26 12:33:11 +02:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-11-06 17:48:56 +01:00
|
|
|
createSyncWithTweak(1, DoneResult::Success),
|
|
|
|
|
createSyncWithTweak(2, DoneResult::Success),
|
|
|
|
|
createSyncWithTweak(3, DoneResult::Success),
|
|
|
|
|
createSyncWithTweak(4, DoneResult::Success),
|
|
|
|
|
createSyncWithTweak(5, DoneResult::Success)
|
2023-04-26 12:33:11 +02:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
2023-11-04 21:46:10 +01:00
|
|
|
{1, Handler::TweakDoneToSuccess},
|
2023-04-26 12:33:11 +02:00
|
|
|
{2, Handler::Sync},
|
2023-11-04 21:46:10 +01:00
|
|
|
{2, Handler::TweakDoneToSuccess},
|
2023-04-26 12:33:11 +02:00
|
|
|
{3, Handler::Sync},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakDoneToSuccess},
|
2023-04-26 12:33:11 +02:00
|
|
|
{4, Handler::Sync},
|
2023-11-04 21:46:10 +01:00
|
|
|
{4, Handler::TweakDoneToSuccess},
|
|
|
|
|
{5, Handler::Sync},
|
|
|
|
|
{5, Handler::TweakDoneToSuccess}
|
2023-04-26 12:33:11 +02:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SyncWithReturn") << TestData{storage, root, log, 0, DoneWith::Success};
|
2023-04-26 12:33:11 +02:00
|
|
|
}
|
|
|
|
|
|
2023-02-06 20:27:59 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-02-06 20:27:59 +01:00
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSync(1),
|
|
|
|
|
createSync(2),
|
|
|
|
|
createSync(3),
|
|
|
|
|
createSync(4),
|
|
|
|
|
createSync(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}
|
|
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SyncParallel") << TestData{storage, root, log, 0, DoneWith::Success};
|
2023-02-06 20:27:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-02-06 20:27:59 +01:00
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSync(1),
|
|
|
|
|
createSync(2),
|
2023-11-06 17:48:56 +01:00
|
|
|
createSyncWithTweak(3, DoneResult::Error),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSync(4),
|
|
|
|
|
createSync(5)
|
2023-02-06 20:27:59 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Sync},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::Sync},
|
|
|
|
|
{3, Handler::TweakDoneToError}
|
2023-02-06 20:27:59 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SyncError") << TestData{storage, root, log, 0, DoneWith::Error};
|
2023-02-06 20:27:59 +01:00
|
|
|
}
|
|
|
|
|
|
2023-02-20 21:32:00 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSync(1),
|
|
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSync(3),
|
|
|
|
|
createSuccessTask(4),
|
|
|
|
|
createSync(5),
|
|
|
|
|
groupDone(0)
|
2023-02-20 21:32:00 +01:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-02-20 21:32:00 +01:00
|
|
|
{3, Handler::Sync},
|
|
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success},
|
2023-02-20 21:32:00 +01:00
|
|
|
{5, Handler::Sync},
|
2023-11-03 10:36:11 +01:00
|
|
|
{0, Handler::GroupSuccess}
|
2023-02-20 21:32:00 +01:00
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SyncAndAsync") << TestData{storage, root, log, 2, DoneWith::Success};
|
2023-02-20 21:32:00 +01:00
|
|
|
}
|
|
|
|
|
|
2023-04-26 12:33:11 +02:00
|
|
|
{
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-27 17:20:40 +02:00
|
|
|
createSync(1),
|
|
|
|
|
createSuccessTask(2),
|
2023-11-06 17:48:56 +01:00
|
|
|
createSyncWithTweak(3, DoneResult::Error),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(4),
|
|
|
|
|
createSync(5),
|
2023-11-03 18:50:32 +01:00
|
|
|
groupDone(0)
|
2023-04-26 12:33:11 +02:00
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Sync},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-04-26 12:33:11 +02:00
|
|
|
{3, Handler::Sync},
|
2023-11-04 21:46:10 +01:00
|
|
|
{3, Handler::TweakDoneToError},
|
2023-04-26 12:33:11 +02:00
|
|
|
{0, Handler::GroupError}
|
|
|
|
|
};
|
2023-11-06 20:08:42 +01:00
|
|
|
QTest::newRow("SyncAndAsyncError") << TestData{storage, root, log, 2, DoneWith::Error};
|
2023-04-26 12:33:11 +02:00
|
|
|
}
|
|
|
|
|
|
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-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-26 23:46:52 +02:00
|
|
|
sequential,
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
2023-02-20 21:32:00 +01:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSuccessTask(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},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success}
|
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 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 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-26 23:46:52 +02:00
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
2023-04-26 23:46:52 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSuccessTask(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},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success}
|
2023-02-20 21:32:00 +01:00
|
|
|
};
|
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.
|
2023-05-18 13:16:40 +02:00
|
|
|
// The minimal requirement for this scenario to succeed is to set parallelLimit(2) or more.
|
2023-04-26 23:46:52 +02:00
|
|
|
const Group root3 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-26 23:46:52 +02:00
|
|
|
parallel,
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSuccessTask(3)
|
2023-04-26 23:46:52 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(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},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success}
|
2023-04-26 23:46:52 +02:00
|
|
|
};
|
|
|
|
|
|
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 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-30 13:31:33 +02:00
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(4)
|
2023-04-30 13:31:33 +02:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(5)
|
2023-04-30 13:31:33 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log4 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{4, Handler::Setup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{5, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success},
|
|
|
|
|
{5, Handler::Success}
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test two separate single barriers.
|
|
|
|
|
|
|
|
|
|
SingleBarrier barrier2;
|
|
|
|
|
|
|
|
|
|
const Group root5 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
|
|
|
|
barrier2,
|
2023-04-30 13:31:33 +02:00
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
|
|
|
|
createBarrierAdvance(storage, barrier2, 2),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(1),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
|
|
|
|
waitForBarrierTask(barrier2)
|
2023-04-30 13:31:33 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(3)
|
2023-04-30 13:31:33 +02:00
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const Log log5 {
|
2023-05-27 17:20:40 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-04-30 13:31:33 +02:00
|
|
|
{1, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::BarrierAdvance},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success}
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
|
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")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, log1, 4, DoneWith::Success};
|
2023-04-30 10:08:12 +02:00
|
|
|
QTest::newRow("BarrierParallelAdvanceFirst")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, log2, 4, DoneWith::Success};
|
2023-04-30 10:08:12 +02:00
|
|
|
QTest::newRow("BarrierParallelWaitForFirst")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, log3, 4, DoneWith::Success};
|
2023-04-30 13:31:33 +02:00
|
|
|
QTest::newRow("BarrierParallelMultiWaitFor")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, log4, 5, DoneWith::Success};
|
2023-04-30 13:31:33 +02:00
|
|
|
QTest::newRow("BarrierParallelTwoSingleBarriers")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root5, log5, 5, DoneWith::Success};
|
2023-04-30 13:31:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
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 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-30 13:31:33 +02:00
|
|
|
sequential,
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
|
|
|
|
createBarrierAdvance(storage, barrier, 2),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(2),
|
|
|
|
|
createSuccessTask(3)
|
2023-04-30 13:31:33 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{2, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success}
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-30 13:31:33 +02:00
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
|
|
|
|
createBarrierAdvance(storage, barrier, 2),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(3),
|
|
|
|
|
createSuccessTask(4)
|
2023-04-30 13:31:33 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log2 {
|
2023-05-27 17:20:40 +02:00
|
|
|
{1, Handler::Setup},
|
2023-04-30 13:31:33 +02:00
|
|
|
{2, Handler::Setup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::BarrierAdvance},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success}
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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.
|
2023-05-18 13:16:40 +02:00
|
|
|
// The minimal requirement for this scenario to succeed is to set parallelLimit(2) or more.
|
2023-04-30 13:31:33 +02:00
|
|
|
const Group root3 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-30 13:31:33 +02:00
|
|
|
parallel,
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(3),
|
|
|
|
|
createSuccessTask(4)
|
2023-04-30 13:31:33 +02:00
|
|
|
},
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
|
|
|
|
createBarrierAdvance(storage, barrier, 2)
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
const Log log3 {
|
|
|
|
|
{2, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{1, Handler::Setup},
|
2023-04-30 13:31:33 +02:00
|
|
|
{2, Handler::Setup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::BarrierAdvance},
|
|
|
|
|
{3, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
2023-05-27 17:20:40 +02:00
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{4, Handler::Success}
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
|
|
|
|
barrier,
|
2023-04-30 13:31:33 +02:00
|
|
|
parallel,
|
2023-05-27 17:20:40 +02:00
|
|
|
createBarrierAdvance(storage, barrier, 1),
|
|
|
|
|
createBarrierAdvance(storage, barrier, 2),
|
2023-04-30 13:31:33 +02:00
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(2),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(3)
|
2023-04-30 13:31:33 +02:00
|
|
|
},
|
|
|
|
|
Group {
|
2023-05-27 17:20:40 +02:00
|
|
|
groupSetup(3),
|
2023-08-01 12:29:35 +02:00
|
|
|
waitForBarrierTask(barrier),
|
2023-05-27 17:20:40 +02:00
|
|
|
createSuccessTask(4)
|
2023-04-30 13:31:33 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const Log log4 {
|
2023-05-27 17:20:40 +02:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
2023-04-30 13:31:33 +02:00
|
|
|
{2, Handler::GroupSetup},
|
|
|
|
|
{3, Handler::GroupSetup},
|
2023-05-27 17:20:40 +02:00
|
|
|
{1, Handler::BarrierAdvance},
|
|
|
|
|
{2, Handler::BarrierAdvance},
|
|
|
|
|
{3, Handler::Setup},
|
2023-04-30 13:31:33 +02:00
|
|
|
{4, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{3, Handler::Success},
|
|
|
|
|
{4, Handler::Success}
|
2023-04-30 13:31:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Notice the different log order for each scenario.
|
|
|
|
|
QTest::newRow("MultiBarrierSequential")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root1, log1, 5, DoneWith::Success};
|
2023-04-30 13:31:33 +02:00
|
|
|
QTest::newRow("MultiBarrierParallelAdvanceFirst")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root2, log2, 5, DoneWith::Success};
|
2023-04-30 13:31:33 +02:00
|
|
|
QTest::newRow("MultiBarrierParallelWaitForFirst")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root3, log3, 5, DoneWith::Success};
|
2023-04-30 13:31:33 +02:00
|
|
|
QTest::newRow("MultiBarrierParallelMultiWaitFor")
|
2023-11-06 20:08:42 +01:00
|
|
|
<< TestData{storage, root4, log4, 6, DoneWith::Success};
|
2023-02-20 21:32:00 +01:00
|
|
|
}
|
2023-05-29 00:13:12 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// Test CustomTask::withTimeout() combinations:
|
|
|
|
|
// 1. When the timeout has triggered or not.
|
|
|
|
|
// 2. With and without timeout handler.
|
|
|
|
|
const Group root1 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-10-31 17:03:48 +01:00
|
|
|
TestTask(setupTask(1, 1000ms), setupDone(1))
|
2023-05-29 00:13:12 +02:00
|
|
|
.withTimeout(1ms)
|
|
|
|
|
};
|
|
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled}
|
2023-05-29 00:13:12 +02:00
|
|
|
};
|
|
|
|
|
QTest::newRow("TaskErrorWithTimeout") << TestData{storage, root1, log1, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-29 00:13:12 +02:00
|
|
|
|
|
|
|
|
const Group root2 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-10-31 17:03:48 +01:00
|
|
|
TestTask(setupTask(1, 1000ms), setupDone(1))
|
2023-05-29 00:13:12 +02:00
|
|
|
.withTimeout(1ms, setupTimeout(1))
|
|
|
|
|
};
|
|
|
|
|
const Log log2 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Timeout},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled}
|
2023-05-29 00:13:12 +02:00
|
|
|
};
|
|
|
|
|
QTest::newRow("TaskErrorWithTimeoutHandler") << TestData{storage, root2, log2, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-29 00:13:12 +02:00
|
|
|
|
|
|
|
|
const Group root3 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-10-31 17:03:48 +01:00
|
|
|
TestTask(setupTask(1, 1ms), setupDone(1))
|
2023-05-29 00:13:12 +02:00
|
|
|
.withTimeout(1000ms)
|
|
|
|
|
};
|
|
|
|
|
const Log doneLog {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success}
|
2023-05-29 00:13:12 +02:00
|
|
|
};
|
|
|
|
|
QTest::newRow("TaskDoneWithTimeout") << TestData{storage, root3, doneLog, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-29 00:13:12 +02:00
|
|
|
|
|
|
|
|
const Group root4 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-10-31 17:03:48 +01:00
|
|
|
TestTask(setupTask(1, 1ms), setupDone(1))
|
2023-05-29 00:13:12 +02:00
|
|
|
.withTimeout(1000ms, setupTimeout(1))
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("TaskDoneWithTimeoutHandler") << TestData{storage, root4, doneLog, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-29 00:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// Test Group::withTimeout() combinations:
|
|
|
|
|
// 1. When the timeout has triggered or not.
|
|
|
|
|
// 2. With and without timeout handler.
|
|
|
|
|
const Group root1 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-29 00:13:12 +02:00
|
|
|
Group {
|
|
|
|
|
createSuccessTask(1, 1000ms)
|
|
|
|
|
}.withTimeout(1ms)
|
|
|
|
|
};
|
|
|
|
|
const Log log1 {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled}
|
2023-05-29 00:13:12 +02:00
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupErrorWithTimeout") << TestData{storage, root1, log1, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-29 00:13:12 +02:00
|
|
|
|
|
|
|
|
// Test Group::withTimeout(), passing custom handler
|
|
|
|
|
const Group root2 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-29 00:13:12 +02:00
|
|
|
Group {
|
|
|
|
|
createSuccessTask(1, 1000ms)
|
|
|
|
|
}.withTimeout(1ms, setupTimeout(1))
|
|
|
|
|
};
|
|
|
|
|
const Log log2 {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Timeout},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Canceled}
|
2023-05-29 00:13:12 +02:00
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupErrorWithTimeoutHandler") << TestData{storage, root2, log2, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Error};
|
2023-05-29 00:13:12 +02:00
|
|
|
|
|
|
|
|
const Group root3 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-29 00:13:12 +02:00
|
|
|
Group {
|
|
|
|
|
createSuccessTask(1, 1ms)
|
|
|
|
|
}.withTimeout(1000ms)
|
|
|
|
|
};
|
|
|
|
|
const Log doneLog {
|
|
|
|
|
{1, Handler::Setup},
|
2023-11-03 10:36:11 +01:00
|
|
|
{1, Handler::Success}
|
2023-05-29 00:13:12 +02:00
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupDoneWithTimeout") << TestData{storage, root3, doneLog, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-29 00:13:12 +02:00
|
|
|
|
|
|
|
|
// Test Group::withTimeout(), passing custom handler
|
|
|
|
|
const Group root4 {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-29 00:13:12 +02:00
|
|
|
Group {
|
|
|
|
|
createSuccessTask(1, 1ms)
|
|
|
|
|
}.withTimeout(1000ms, setupTimeout(1))
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("GroupDoneWithTimeoutHandler") << TestData{storage, root4, doneLog, 2,
|
2023-11-06 20:08:42 +01:00
|
|
|
DoneWith::Success};
|
2023-05-29 00:13:12 +02:00
|
|
|
}
|
2023-11-04 23:51:17 +01:00
|
|
|
|
2024-01-02 11:32:10 +01:00
|
|
|
{
|
|
|
|
|
// Test if the task tree started from the setup handler may use the same storage.
|
|
|
|
|
|
|
|
|
|
const auto groupSetup = [storage] {
|
|
|
|
|
storage->m_log.append({0, Handler::GroupSetup});
|
|
|
|
|
|
|
|
|
|
const auto nestedGroupSetup = [storage] {
|
|
|
|
|
storage->m_log.append({2, Handler::GroupSetup});
|
|
|
|
|
};
|
|
|
|
|
const auto nestedGroupDone = [storage](DoneWith result) {
|
|
|
|
|
storage->m_log.append({2, resultToGroupHandler(result)});
|
|
|
|
|
};
|
|
|
|
|
TaskTree subTree({storage,
|
|
|
|
|
onGroupSetup(nestedGroupSetup),
|
|
|
|
|
onGroupDone(nestedGroupDone)});
|
|
|
|
|
subTree.start();
|
|
|
|
|
storage->m_log.append({1, Handler::GroupSetup}); // Ensure the storage is still active.
|
|
|
|
|
};
|
|
|
|
|
const auto groupDone = [storage](DoneWith result) {
|
|
|
|
|
storage->m_log.append({0, resultToGroupHandler(result)});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group root {
|
|
|
|
|
storage,
|
|
|
|
|
onGroupSetup(groupSetup),
|
|
|
|
|
onGroupDone(groupDone)
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{0, Handler::GroupSetup},
|
|
|
|
|
{1, Handler::GroupSetup},
|
|
|
|
|
{0, Handler::GroupSuccess}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("CommonStorage") << TestData{storage, root, log, 0, DoneWith::Success};
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 14:17:07 +01:00
|
|
|
{
|
|
|
|
|
const Group root {
|
|
|
|
|
storage,
|
|
|
|
|
Group {
|
|
|
|
|
parallel,
|
|
|
|
|
createSuccessTask(1, 100ms),
|
|
|
|
|
Group {
|
|
|
|
|
createFailingTask(2, 10ms),
|
|
|
|
|
createSuccessTask(3, 10ms)
|
|
|
|
|
},
|
|
|
|
|
createSuccessTask(4, 10ms)
|
|
|
|
|
},
|
|
|
|
|
createSuccessTask(5, 10ms)
|
|
|
|
|
};
|
|
|
|
|
const Log log {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{4, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{1, Handler::Canceled},
|
|
|
|
|
{4, Handler::Canceled}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("NestedCancel") << TestData{storage, root, log, 5, DoneWith::Error};
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 22:39:40 +01:00
|
|
|
{
|
2024-01-11 21:15:01 +01:00
|
|
|
const QList<GroupItem> successItems {
|
2024-01-09 22:39:40 +01:00
|
|
|
storage,
|
2024-01-10 20:27:33 +01:00
|
|
|
LoopRepeat(2),
|
2024-01-09 22:39:40 +01:00
|
|
|
createSuccessTask(1),
|
|
|
|
|
createSuccessTask(2)
|
|
|
|
|
};
|
|
|
|
|
|
2024-01-11 21:15:01 +01:00
|
|
|
const Group rootSequentialSuccess {
|
2024-01-09 22:39:40 +01:00
|
|
|
sequential,
|
2024-01-11 21:15:01 +01:00
|
|
|
successItems
|
2024-01-09 22:39:40 +01:00
|
|
|
};
|
2024-01-11 21:15:01 +01:00
|
|
|
const Log logSequentialSuccess {
|
2024-01-09 22:39:40 +01:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Success}
|
|
|
|
|
};
|
|
|
|
|
|
2024-01-11 21:15:01 +01:00
|
|
|
const Group rootParallelSuccess {
|
2024-01-09 22:39:40 +01:00
|
|
|
parallel,
|
2024-01-11 21:15:01 +01:00
|
|
|
successItems
|
2024-01-09 22:39:40 +01:00
|
|
|
};
|
2024-01-11 21:15:01 +01:00
|
|
|
const Log logParallelSuccess {
|
2024-01-09 22:39:40 +01:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Success}
|
|
|
|
|
};
|
|
|
|
|
|
2024-01-11 21:15:01 +01:00
|
|
|
const Group rootParallelLimitSuccess {
|
2024-01-09 22:39:40 +01:00
|
|
|
parallelLimit(2),
|
2024-01-11 21:15:01 +01:00
|
|
|
successItems
|
2024-01-09 22:39:40 +01:00
|
|
|
};
|
2024-01-11 21:15:01 +01:00
|
|
|
const Log logParallelLimitSuccess {
|
2024-01-09 22:39:40 +01:00
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Success}
|
|
|
|
|
};
|
|
|
|
|
|
2024-01-11 21:15:01 +01:00
|
|
|
const QList<GroupItem> errorItems {
|
|
|
|
|
storage,
|
|
|
|
|
LoopRepeat(2),
|
|
|
|
|
createSuccessTask(1),
|
|
|
|
|
createFailingTask(2)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group rootSequentialError {
|
|
|
|
|
sequential,
|
|
|
|
|
errorItems
|
|
|
|
|
};
|
|
|
|
|
const Log logSequentialError {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Error}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group rootParallelError {
|
|
|
|
|
parallel,
|
|
|
|
|
errorItems
|
|
|
|
|
};
|
|
|
|
|
const Log logParallelError {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{1, Handler::Canceled},
|
|
|
|
|
{2, Handler::Canceled}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group rootParallelLimitError {
|
|
|
|
|
parallelLimit(2),
|
|
|
|
|
errorItems
|
|
|
|
|
};
|
|
|
|
|
const Log logParallelLimitError {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Error},
|
|
|
|
|
{1, Handler::Canceled}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QTest::newRow("RepeatSequentialSuccess")
|
|
|
|
|
<< TestData{storage, rootSequentialSuccess, logSequentialSuccess, 4, DoneWith::Success};
|
|
|
|
|
QTest::newRow("RepeatParallelSuccess")
|
|
|
|
|
<< TestData{storage, rootParallelSuccess, logParallelSuccess, 4, DoneWith::Success};
|
|
|
|
|
QTest::newRow("RepeatParallelLimitSuccess")
|
|
|
|
|
<< TestData{storage, rootParallelLimitSuccess, logParallelLimitSuccess, 4, DoneWith::Success};
|
|
|
|
|
QTest::newRow("RepeatSequentialError")
|
|
|
|
|
<< TestData{storage, rootSequentialError, logSequentialError, 4, DoneWith::Error};
|
|
|
|
|
QTest::newRow("RepeatParallelError")
|
|
|
|
|
<< TestData{storage, rootParallelError, logParallelError, 4, DoneWith::Error};
|
|
|
|
|
QTest::newRow("RepeatParallelLimitError")
|
|
|
|
|
<< TestData{storage, rootParallelLimitError, logParallelLimitError, 4, DoneWith::Error};
|
2024-01-09 22:39:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
2024-02-14 23:05:38 +01:00
|
|
|
const LoopUntil loop([](int index) { return index < 3; });
|
2024-01-09 22:39:40 +01:00
|
|
|
|
|
|
|
|
const auto onSetupContinue = [storage, loop](int taskId) {
|
|
|
|
|
return [storage, loop, taskId](TaskObject &) {
|
|
|
|
|
storage->m_log.append({loop.iteration() * 10 + taskId, Handler::Setup});
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto onSetupStop = [storage, loop](int taskId) {
|
|
|
|
|
return [storage, loop, taskId](TaskObject &) {
|
|
|
|
|
storage->m_log.append({loop.iteration() * 10 + taskId, Handler::Setup});
|
|
|
|
|
if (loop.iteration() == 2)
|
|
|
|
|
return SetupResult::StopWithSuccess;
|
|
|
|
|
return SetupResult::Continue;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto onDone = [storage, loop](int taskId) {
|
|
|
|
|
return [storage, loop, taskId](DoneWith doneWith) {
|
|
|
|
|
const Handler handler = doneWith == DoneWith::Cancel ? Handler::Canceled
|
|
|
|
|
: doneWith == DoneWith::Success ? Handler::Success : Handler::Error;
|
|
|
|
|
storage->m_log.append({loop.iteration() * 10 + taskId, handler});
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const QList<GroupItem> items {
|
|
|
|
|
storage,
|
|
|
|
|
loop,
|
|
|
|
|
TestTask(onSetupContinue(1), onDone(1)),
|
|
|
|
|
TestTask(onSetupStop(2), onDone(2))
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group rootSequential {
|
|
|
|
|
sequential,
|
|
|
|
|
items
|
|
|
|
|
};
|
|
|
|
|
const Log logSequential {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{11, Handler::Setup},
|
|
|
|
|
{11, Handler::Success},
|
|
|
|
|
{12, Handler::Setup},
|
|
|
|
|
{12, Handler::Success},
|
|
|
|
|
{21, Handler::Setup},
|
|
|
|
|
{21, Handler::Success},
|
|
|
|
|
{22, Handler::Setup}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group rootParallel {
|
|
|
|
|
parallel,
|
|
|
|
|
items
|
|
|
|
|
};
|
|
|
|
|
const Log logParallel {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{11, Handler::Setup},
|
|
|
|
|
{12, Handler::Setup},
|
|
|
|
|
{21, Handler::Setup},
|
|
|
|
|
{22, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{11, Handler::Success},
|
|
|
|
|
{12, Handler::Success},
|
|
|
|
|
{21, Handler::Success}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Group rootParallelLimit {
|
|
|
|
|
parallelLimit(2),
|
|
|
|
|
items
|
|
|
|
|
};
|
|
|
|
|
const Log logParallelLimit {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{2, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{11, Handler::Setup},
|
|
|
|
|
{2, Handler::Success},
|
|
|
|
|
{12, Handler::Setup},
|
|
|
|
|
{11, Handler::Success},
|
|
|
|
|
{21, Handler::Setup},
|
|
|
|
|
{12, Handler::Success},
|
|
|
|
|
{22, Handler::Setup},
|
|
|
|
|
{21, Handler::Success}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QTest::newRow("LoopSequential")
|
|
|
|
|
<< TestData{storage, rootSequential, logSequential, 2, DoneWith::Success};
|
|
|
|
|
QTest::newRow("LoopParallel")
|
|
|
|
|
<< TestData{storage, rootParallel, logParallel, 2, DoneWith::Success};
|
|
|
|
|
QTest::newRow("LoopParallelLimit")
|
|
|
|
|
<< TestData{storage, rootParallelLimit, logParallelLimit, 2, DoneWith::Success};
|
|
|
|
|
}
|
2024-01-24 12:11:17 +01:00
|
|
|
|
2024-02-14 23:05:38 +01:00
|
|
|
{
|
|
|
|
|
// Check if task tree finishes with the right progress value when LoopUntil(false).
|
|
|
|
|
const Group root {
|
|
|
|
|
storage,
|
|
|
|
|
LoopUntil([](int) { return false; }),
|
|
|
|
|
createSuccessTask(1)
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("ProgressWithLoopUntilFalse")
|
|
|
|
|
<< TestData{storage, root, {}, 1, DoneWith::Success};
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-24 12:11:17 +01:00
|
|
|
{
|
|
|
|
|
const auto createRoot = [=](DoneResult doneResult, CallDoneIf callDoneIf) {
|
|
|
|
|
return Group {
|
|
|
|
|
storage,
|
|
|
|
|
Group {
|
|
|
|
|
createTask(1, doneResult)
|
|
|
|
|
},
|
|
|
|
|
groupDone(2, callDoneIf)
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Log logSuccessLong {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Success},
|
|
|
|
|
{2, Handler::GroupSuccess}
|
|
|
|
|
};
|
|
|
|
|
const Log logSuccessShort {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Success}
|
|
|
|
|
};
|
|
|
|
|
const Log logErrorLong {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Error},
|
|
|
|
|
{2, Handler::GroupError}
|
|
|
|
|
};
|
|
|
|
|
const Log logErrorShort {
|
|
|
|
|
{1, Handler::Setup},
|
|
|
|
|
{1, Handler::Error}
|
|
|
|
|
};
|
|
|
|
|
QTest::newRow("CallDoneIfGroupSuccessOrErrorAfterSuccess")
|
|
|
|
|
<< TestData{storage, createRoot(DoneResult::Success, CallDoneIf::SuccessOrError),
|
|
|
|
|
logSuccessLong, 1, DoneWith::Success};
|
|
|
|
|
QTest::newRow("CallDoneIfGroupSuccessAfterSuccess")
|
|
|
|
|
<< TestData{storage, createRoot(DoneResult::Success, CallDoneIf::Success),
|
|
|
|
|
logSuccessLong, 1, DoneWith::Success};
|
|
|
|
|
QTest::newRow("CallDoneIfGroupErrorAfterSuccess")
|
|
|
|
|
<< TestData{storage, createRoot(DoneResult::Success, CallDoneIf::Error),
|
|
|
|
|
logSuccessShort, 1, DoneWith::Success};
|
|
|
|
|
QTest::newRow("CallDoneIfGroupSuccessOrErrorAfterError")
|
|
|
|
|
<< TestData{storage, createRoot(DoneResult::Error, CallDoneIf::SuccessOrError),
|
|
|
|
|
logErrorLong, 1, DoneWith::Error};
|
|
|
|
|
QTest::newRow("CallDoneIfGroupSuccessAfterError")
|
|
|
|
|
<< TestData{storage, createRoot(DoneResult::Error, CallDoneIf::Success),
|
|
|
|
|
logErrorShort, 1, DoneWith::Error};
|
|
|
|
|
QTest::newRow("CallDoneIfGroupErrorAfterError")
|
|
|
|
|
<< TestData{storage, createRoot(DoneResult::Error, CallDoneIf::Error),
|
|
|
|
|
logErrorLong, 1, DoneWith::Error};
|
|
|
|
|
}
|
2024-01-09 22:39:40 +01:00
|
|
|
|
2024-01-02 11:32:10 +01:00
|
|
|
// This test checks if storage shadowing works OK.
|
2023-11-13 13:01:55 +01:00
|
|
|
QTest::newRow("StorageShadowing") << storageShadowingData();
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-10 21:38:41 +02:00
|
|
|
void tst_Tasking::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
|
|
|
|
2023-05-29 01:10:39 +02:00
|
|
|
TaskTree taskTree({testData.root.withTimeout(1000ms)});
|
|
|
|
|
QCOMPARE(taskTree.taskCount() - 1, testData.taskCount); // -1 for the timeout task above
|
2022-12-05 18:08:48 +01:00
|
|
|
Log actualLog;
|
2023-08-31 19:25:59 +02:00
|
|
|
const auto collectLog = [&actualLog](const CustomStorage &storage) {
|
|
|
|
|
actualLog = storage.m_log;
|
|
|
|
|
};
|
2023-01-26 19:06:02 +01:00
|
|
|
taskTree.onStorageDone(testData.storage, collectLog);
|
2023-11-06 20:08:42 +01:00
|
|
|
const DoneWith result = taskTree.runBlocking();
|
2023-05-16 23:21:55 +02:00
|
|
|
QCOMPARE(taskTree.isRunning(), false);
|
2022-11-25 12:35:07 +01:00
|
|
|
|
2023-05-29 01:10:39 +02:00
|
|
|
QCOMPARE(taskTree.progressValue(), taskTree.progressMaximum());
|
2023-01-26 19:06:02 +01:00
|
|
|
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-05-26 11:05:35 +02:00
|
|
|
QCOMPARE(result, testData.onDone);
|
2022-10-12 14:30:24 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-06 08:29:33 +01:00
|
|
|
void tst_Tasking::testInThread_data()
|
|
|
|
|
{
|
|
|
|
|
QTest::addColumn<TestData>("testData");
|
2023-11-13 13:01:55 +01:00
|
|
|
QTest::newRow("StorageShadowing") << storageShadowingData();
|
|
|
|
|
QTest::newRow("Parallel") << parallelData();
|
2023-11-06 08:29:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct TestResult
|
|
|
|
|
{
|
|
|
|
|
int executeCount = 0;
|
|
|
|
|
ThreadResult threadResult = ThreadResult::Success;
|
2023-11-13 13:01:55 +01:00
|
|
|
Log actualLog = {};
|
2023-11-06 08:29:33 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const int s_loopCount = 1000;
|
|
|
|
|
static const int s_threadCount = 12;
|
|
|
|
|
|
|
|
|
|
static void runInThread(QPromise<TestResult> &promise, const TestData &testData)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < s_loopCount; ++i) {
|
|
|
|
|
if (promise.isCanceled()) {
|
|
|
|
|
promise.addResult(TestResult{i, ThreadResult::Canceled});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TaskTree taskTree({testData.root.withTimeout(1000ms)});
|
|
|
|
|
if (taskTree.taskCount() - 1 != testData.taskCount) { // -1 for the timeout task above
|
|
|
|
|
promise.addResult(TestResult{i, ThreadResult::FailOnTaskCountCheck});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Log actualLog;
|
|
|
|
|
const auto collectLog = [&actualLog](const CustomStorage &storage) {
|
|
|
|
|
actualLog = storage.m_log;
|
|
|
|
|
};
|
|
|
|
|
taskTree.onStorageDone(testData.storage, collectLog);
|
|
|
|
|
|
2023-11-06 20:08:42 +01:00
|
|
|
const DoneWith result = taskTree.runBlocking(QFuture<void>(promise.future()));
|
2023-11-06 08:29:33 +01:00
|
|
|
|
|
|
|
|
if (taskTree.isRunning()) {
|
|
|
|
|
promise.addResult(TestResult{i, ThreadResult::FailOnRunningCheck});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (taskTree.progressValue() != taskTree.progressMaximum()) {
|
|
|
|
|
promise.addResult(TestResult{i, ThreadResult::FailOnProgressCheck});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (actualLog != testData.expectedLog) {
|
2023-11-13 13:01:55 +01:00
|
|
|
promise.addResult(TestResult{i, ThreadResult::FailOnLogCheck, actualLog});
|
2023-11-06 08:29:33 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (result != testData.onDone) {
|
|
|
|
|
promise.addResult(TestResult{i, ThreadResult::FailOnDoneStatusCheck});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-13 13:01:55 +01:00
|
|
|
promise.addResult(TestResult{s_loopCount, ThreadResult::Success, testData.expectedLog});
|
2023-11-06 08:29:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tst_Tasking::testInThread()
|
|
|
|
|
{
|
|
|
|
|
QFETCH(TestData, testData);
|
|
|
|
|
|
|
|
|
|
const auto onSetup = [testData](ConcurrentCall<TestResult> &task) {
|
2023-11-08 09:49:03 +01:00
|
|
|
task.setConcurrentCallData(&runInThread, testData);
|
2023-11-06 08:29:33 +01:00
|
|
|
};
|
|
|
|
|
const auto onDone = [testData](const ConcurrentCall<TestResult> &task) {
|
|
|
|
|
QVERIFY(task.future().resultCount());
|
|
|
|
|
const TestResult result = task.result();
|
2023-11-13 13:01:55 +01:00
|
|
|
QCOMPARE(result.actualLog, testData.expectedLog);
|
2023-11-06 08:29:33 +01:00
|
|
|
QCOMPARE(result.threadResult, ThreadResult::Success);
|
2023-11-13 13:01:55 +01:00
|
|
|
QCOMPARE(result.executeCount, s_loopCount);
|
2023-11-06 08:29:33 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QList<GroupItem> tasks = { parallel };
|
|
|
|
|
for (int i = 0; i < s_threadCount; ++i)
|
|
|
|
|
tasks.append(ConcurrentCallTask<TestResult>(onSetup, onDone));
|
|
|
|
|
|
|
|
|
|
TaskTree taskTree(Group{tasks});
|
2023-11-06 20:08:42 +01:00
|
|
|
const DoneWith result = taskTree.runBlocking();
|
2023-11-06 08:29:33 +01:00
|
|
|
QCOMPARE(taskTree.isRunning(), false);
|
|
|
|
|
|
|
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 0);
|
|
|
|
|
QCOMPARE(result, testData.onDone);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-31 20:10:31 +02:00
|
|
|
struct StorageIO
|
|
|
|
|
{
|
|
|
|
|
int value = 0;
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-19 14:50:55 +01:00
|
|
|
static Group inputOutputRecipe(const Storage<StorageIO> &storage)
|
2023-08-31 20:10:31 +02:00
|
|
|
{
|
|
|
|
|
return Group {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-08-31 20:10:31 +02:00
|
|
|
onGroupSetup([storage] { ++storage->value; }),
|
|
|
|
|
onGroupDone([storage] { storage->value *= 2; })
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tst_Tasking::storageIO_data()
|
|
|
|
|
{
|
|
|
|
|
QTest::addColumn<int>("input");
|
|
|
|
|
QTest::addColumn<int>("output");
|
|
|
|
|
|
|
|
|
|
QTest::newRow("-1 -> 0") << -1 << 0;
|
|
|
|
|
QTest::newRow("0 -> 2") << 0 << 2;
|
|
|
|
|
QTest::newRow("1 -> 4") << 1 << 4;
|
|
|
|
|
QTest::newRow("2 -> 6") << 2 << 6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tst_Tasking::storageIO()
|
|
|
|
|
{
|
|
|
|
|
QFETCH(int, input);
|
|
|
|
|
QFETCH(int, output);
|
|
|
|
|
|
|
|
|
|
int actualOutput = 0;
|
|
|
|
|
|
2023-11-19 14:50:55 +01:00
|
|
|
const Storage<StorageIO> storage;
|
2023-08-31 20:10:31 +02:00
|
|
|
TaskTree taskTree(inputOutputRecipe(storage));
|
|
|
|
|
|
|
|
|
|
const auto setInput = [input](StorageIO &storage) { storage.value = input; };
|
|
|
|
|
const auto getOutput = [&actualOutput](const StorageIO &storage) { actualOutput = storage.value; };
|
|
|
|
|
|
|
|
|
|
taskTree.onStorageSetup(storage, setInput);
|
|
|
|
|
taskTree.onStorageDone(storage, getOutput);
|
|
|
|
|
taskTree.runBlocking();
|
|
|
|
|
|
|
|
|
|
QCOMPARE(taskTree.isRunning(), false);
|
|
|
|
|
QCOMPARE(actualOutput, output);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-10 21:38:41 +02:00
|
|
|
void tst_Tasking::storageOperators()
|
2022-11-22 15:21:45 +01:00
|
|
|
{
|
2023-11-19 14:50:55 +01:00
|
|
|
StorageBase storage1 = Storage<CustomStorage>();
|
|
|
|
|
StorageBase storage2 = Storage<CustomStorage>();
|
2023-11-19 14:40:49 +01:00
|
|
|
StorageBase 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.
|
2023-05-10 21:38:41 +02:00
|
|
|
void tst_Tasking::storageDestructor()
|
2022-12-04 08:31:14 +01:00
|
|
|
{
|
2023-02-21 12:05:18 +01:00
|
|
|
bool setupCalled = false;
|
2023-08-31 18:31:34 +02:00
|
|
|
const auto setupHandler = [&setupCalled](CustomStorage &) {
|
2023-02-21 12:05:18 +01:00
|
|
|
setupCalled = true;
|
|
|
|
|
};
|
|
|
|
|
bool doneCalled = false;
|
2023-08-31 19:25:59 +02:00
|
|
|
const auto doneHandler = [&doneCalled](const CustomStorage &) {
|
2023-02-21 12:05:18 +01:00
|
|
|
doneCalled = true;
|
|
|
|
|
};
|
2022-11-22 15:21:45 +01:00
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 0);
|
|
|
|
|
{
|
2023-11-19 14:50:55 +01:00
|
|
|
Storage<CustomStorage> storage;
|
2023-05-27 17:20:40 +02:00
|
|
|
const auto setupSleepingTask = [](TaskObject &taskObject) {
|
|
|
|
|
taskObject = 1000ms;
|
2022-11-22 15:21:45 +01:00
|
|
|
};
|
|
|
|
|
const Group root {
|
2023-11-19 14:18:41 +01:00
|
|
|
storage,
|
2023-05-28 22:47:59 +02:00
|
|
|
TestTask(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);
|
|
|
|
|
}
|
|
|
|
|
QCOMPARE(CustomStorage::instanceCount(), 0);
|
2023-02-21 12:05:18 +01:00
|
|
|
QVERIFY(setupCalled);
|
|
|
|
|
QVERIFY(!doneCalled);
|
2022-11-22 15:21:45 +01:00
|
|
|
}
|
|
|
|
|
|
2024-01-06 13:54:32 +01:00
|
|
|
void tst_Tasking::restart()
|
|
|
|
|
{
|
|
|
|
|
TaskTree taskTree({TestTask([](TaskObject &taskObject) { taskObject = 1000ms; })});
|
|
|
|
|
taskTree.start();
|
|
|
|
|
QVERIFY(taskTree.isRunning());
|
2024-01-24 22:52:36 +01:00
|
|
|
taskTree.cancel();
|
2024-01-06 13:54:32 +01:00
|
|
|
QVERIFY(!taskTree.isRunning());
|
|
|
|
|
taskTree.start();
|
|
|
|
|
QVERIFY(taskTree.isRunning());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-14 15:06:27 +01:00
|
|
|
class BrokenTaskAdapter : public TaskAdapter<int>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
// QTCREATORBUG-30204
|
|
|
|
|
~BrokenTaskAdapter() { emit done(DoneResult::Success); }
|
|
|
|
|
void start() {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using BrokenTask = CustomTask<BrokenTaskAdapter>;
|
|
|
|
|
|
|
|
|
|
void tst_Tasking::destructorOfTaskEmittingDone()
|
|
|
|
|
{
|
|
|
|
|
TaskTree taskTree({BrokenTask()});
|
|
|
|
|
taskTree.start();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-10 21:38:41 +02:00
|
|
|
QTEST_GUILESS_MAIN(tst_Tasking)
|
2022-10-12 14:30:24 +02:00
|
|
|
|
2023-05-10 21:38:41 +02:00
|
|
|
#include "tst_tasking.moc"
|