TaskTree: Introduce Timeout task

By default, when finished, it returns success.
In order to convert it into failing task,
enclose it inside a Group with finishAllAndError.

Reuse it in tasking tests.

Task-number: QTCREATORBUG-28741
Change-Id: Ic81203203e0b139d4f9bfd553279ecb01cd303f4
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Jarek Kobus
2023-05-28 22:47:59 +02:00
parent 5e9eadfc58
commit f6e7dbd416
3 changed files with 47 additions and 34 deletions

View File

@@ -1848,4 +1848,14 @@ void TaskTreeTaskAdapter::start()
task()->start(); task()->start();
} }
TimeoutTaskAdapter::TimeoutTaskAdapter()
{
*task() = std::chrono::milliseconds::zero();
}
void TimeoutTaskAdapter::start()
{
QTimer::singleShot(*task(), this, [this] { emit done(true); });
}
} // namespace Tasking } // namespace Tasking

View File

@@ -426,6 +426,13 @@ public:
void start() final; void start() final;
}; };
class TASKING_EXPORT TimeoutTaskAdapter : public TaskAdapter<std::chrono::milliseconds>
{
public:
TimeoutTaskAdapter();
void start() final;
};
} // namespace Tasking } // namespace Tasking
#define TASKING_DECLARE_TASK(CustomTaskName, TaskAdapterClass)\ #define TASKING_DECLARE_TASK(CustomTaskName, TaskAdapterClass)\
@@ -438,3 +445,4 @@ using CustomTaskName = CustomTask<TaskAdapterClass<Args...>>;\
} // namespace Tasking } // namespace Tasking
TASKING_DECLARE_TASK(TaskTreeTask, TaskTreeTaskAdapter); TASKING_DECLARE_TASK(TaskTreeTask, TaskTreeTaskAdapter);
TASKING_DECLARE_TASK(TimeoutTask, TimeoutTaskAdapter);

View File

@@ -3,26 +3,15 @@
#include <tasking/barrier.h> #include <tasking/barrier.h>
#include <QTimer>
#include <QtTest> #include <QtTest>
using namespace Tasking;
using namespace std::chrono; using namespace std::chrono;
using namespace std::chrono_literals; using namespace std::chrono_literals;
using namespace Tasking;
template <bool SuccessOnDone>
class DurationTaskAdapter : public TaskAdapter<std::chrono::milliseconds>
{
public:
DurationTaskAdapter() { *task() = std::chrono::milliseconds{0}; }
void start() final { QTimer::singleShot(*task(), this, [this] { emit done(SuccessOnDone); }); }
};
TASKING_DECLARE_TASK(SuccessTask, DurationTaskAdapter<true>);
TASKING_DECLARE_TASK(FailingTask, DurationTaskAdapter<false>);
using TaskObject = milliseconds; using TaskObject = milliseconds;
using TestTask = TimeoutTask;
namespace PrintableEnums { namespace PrintableEnums {
@@ -86,9 +75,9 @@ void tst_Tasking::validConstructs()
{ {
const Group task { const Group task {
parallel, parallel,
SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), TestTask([](TaskObject &) {}, [](const TaskObject &) {}),
SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), TestTask([](TaskObject &) {}, [](const TaskObject &) {}),
SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}) TestTask([](TaskObject &) {}, [](const TaskObject &) {})
}; };
const Group group1 { const Group group1 {
@@ -99,18 +88,18 @@ void tst_Tasking::validConstructs()
parallel, parallel,
Group { Group {
parallel, parallel,
SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), TestTask([](TaskObject &) {}, [](const TaskObject &) {}),
Group { Group {
parallel, parallel,
SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), TestTask([](TaskObject &) {}, [](const TaskObject &) {}),
Group { Group {
parallel, parallel,
SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}) TestTask([](TaskObject &) {}, [](const TaskObject &) {})
} }
}, },
Group { Group {
parallel, parallel,
SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), TestTask([](TaskObject &) {}, [](const TaskObject &) {}),
onGroupDone([] {}) onGroupDone([] {})
} }
}, },
@@ -127,24 +116,24 @@ void tst_Tasking::validConstructs()
const Group task2 { const Group task2 {
parallel, parallel,
SuccessTask(setupHandler), TestTask(setupHandler),
SuccessTask(setupHandler, doneHandler), TestTask(setupHandler, doneHandler),
SuccessTask(setupHandler, doneHandler, errorHandler), TestTask(setupHandler, doneHandler, errorHandler),
// need to explicitly pass empty handler for done // need to explicitly pass empty handler for done
SuccessTask(setupHandler, {}, errorHandler) TestTask(setupHandler, {}, errorHandler)
}; };
// Fluent interface // Fluent interface
const Group fluent { const Group fluent {
parallel, parallel,
SuccessTask().onSetup(setupHandler), TestTask().onSetup(setupHandler),
SuccessTask().onSetup(setupHandler).onDone(doneHandler), TestTask().onSetup(setupHandler).onDone(doneHandler),
SuccessTask().onSetup(setupHandler).onDone(doneHandler).onError(errorHandler), TestTask().onSetup(setupHandler).onDone(doneHandler).onError(errorHandler),
// possible to skip the empty done // possible to skip the empty done
SuccessTask().onSetup(setupHandler).onError(errorHandler), TestTask().onSetup(setupHandler).onError(errorHandler),
// possible to set handlers in a different order // possible to set handlers in a different order
SuccessTask().onError(errorHandler).onDone(doneHandler).onSetup(setupHandler), TestTask().onError(errorHandler).onDone(doneHandler).onSetup(setupHandler),
}; };
@@ -259,8 +248,14 @@ void tst_Tasking::testTree_data()
const auto createTask = [storage, setupTask, setupDone, setupError]( const auto createTask = [storage, setupTask, setupDone, setupError](
int taskId, bool successTask, milliseconds timeout = 0ms) -> TaskItem { int taskId, bool successTask, milliseconds timeout = 0ms) -> TaskItem {
if (successTask) if (successTask)
return SuccessTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); return TestTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId));
return FailingTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); const Group root {
finishAllAndError,
TestTask(setupTask(taskId, timeout)),
onGroupDone([storage, taskId] { storage->m_log.append({taskId, Handler::Done}); }),
onGroupError([storage, taskId] { storage->m_log.append({taskId, Handler::Error}); })
};
return root;
}; };
const auto createSuccessTask = [createTask](int taskId, milliseconds timeout = 0ms) { const auto createSuccessTask = [createTask](int taskId, milliseconds timeout = 0ms) {
@@ -273,7 +268,7 @@ void tst_Tasking::testTree_data()
const auto createDynamicTask = [storage, setupDynamicTask, setupDone, setupError]( const auto createDynamicTask = [storage, setupDynamicTask, setupDone, setupError](
int taskId, TaskAction action) { int taskId, TaskAction action) {
return SuccessTask(setupDynamicTask(taskId, action), setupDone(taskId), setupError(taskId)); return TestTask(setupDynamicTask(taskId, action), setupDone(taskId), setupError(taskId));
}; };
const auto groupSetup = [storage](int taskId) { const auto groupSetup = [storage](int taskId) {
@@ -2142,7 +2137,7 @@ void tst_Tasking::storageDestructor()
}; };
const Group root { const Group root {
Storage(storage), Storage(storage),
SuccessTask(setupSleepingTask) TestTask(setupSleepingTask)
}; };
TaskTree taskTree(root); TaskTree taskTree(root);