userver: userver/testsuite/tasks.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
tasks.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/testsuite/tasks.hpp
4/// @brief @copybrief testsuite::TestsuiteTasks
5
6#include <atomic>
7#include <functional>
8#include <memory>
9#include <string>
10#include <unordered_map>
11
12#include <userver/components/component_fwd.hpp>
13#include <userver/concurrent/variable.hpp>
14#include <userver/engine/task/task_with_result.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace testsuite {
19
20class TaskNotFound final : public std::runtime_error {
21 using std::runtime_error::runtime_error;
22};
23
24class TaskAlreadyRunning final : public std::runtime_error {
25 using std::runtime_error::runtime_error;
26};
27
28// clang-format off
29
30/// @brief Testsuite tasks support
31///
32/// A testsuite task is a function that can be called from testsuite by its name.
33/// Only one task with the same name can be run simultaneously.
34///
35
36// clang-format on
37class TestsuiteTasks final {
38 public:
39 /// Task function type
40 using TaskCallback = std::function<void()>;
41
42 explicit TestsuiteTasks(bool is_enabled);
43 ~TestsuiteTasks();
44
45 /// @brief Are testsuite tasks enabled or not
46 ///
47 /// It is recommended to register tasks only for testsuite environment. Use
48 /// this method to test weather or not you are running under testsuite:
49 /// @code
50 /// if (testsuite_tasks.IsEnabled()) {
51 /// // testsuite code goes here...
52 /// } else {
53 /// // production code goes here...
54 /// }
55 /// @endcode
56 bool IsEnabled() const { return is_enabled_; }
57
58 /// @brief Register new task
59 /// @param name Task name
60 /// @param callback Testsuite task callback function
61 /// @throws std::runtime_error When task with `name` is already registered.
62 void RegisterTask(const std::string& name, TaskCallback callback);
63
64 /// @brief Unregister task
65 /// @param name Task name
66 /// @throws std::runtime_error When task `name` is not known.
67 void UnregisterTask(const std::string& name);
68
69 /// @brief Run task by name and waits for it to finish
70 /// @param name Task name
71 /// @throws TaskAlreadyRunning When task `name` is already running.
72 void RunTask(const std::string& name);
73
74 /// @brief Asynchronously starts the task
75 /// @param name Task name
76 /// @returns Task id
77 /// @throws TaskAlreadyRunning When task `name` is already running.
78 std::string SpawnTask(const std::string& name);
79
80 /// @brief Stop previously spawned task
81 /// @param task_id Task id returned by `SpawnTask()`
82 /// @throws TaskNotFound When task `task_id` is not known.
83 void StopSpawnedTask(const std::string& task_id);
84
85 /// @brief Checks that there are no running tasks left.
86 ///
87 /// Must be called on service shutdown. Aborts process when there are tasks
88 /// running.
89 void CheckNoRunningTasks() noexcept;
90
91 /// @brief Returns list of registered task names
93
94 private:
95 struct Entry {
96 std::atomic<bool> running_flag{false};
97 TaskCallback callback;
98 };
99
100 struct SpawnedTask {
101 std::atomic<bool> busy_flag{false};
102 std::string name;
103 engine::TaskWithResult<void> task;
104 };
105
106 std::shared_ptr<Entry> GetEntryFor(const std::string& name);
107 std::shared_ptr<SpawnedTask> GetSpawnedFor(const std::string& task_id);
108
109 const bool is_enabled_;
110
111 using TasksMap = std::unordered_map<std::string, std::shared_ptr<Entry>>;
112 concurrent::Variable<TasksMap> tasks_;
113
114 using SpawnedMap =
115 std::unordered_map<std::string, std::shared_ptr<SpawnedTask>>;
116 concurrent::Variable<SpawnedMap> spawned_;
117};
118
119/// @brief Get reference to TestsuiteTasks instance
120/// @param component_context
121TestsuiteTasks& GetTestsuiteTasks(
122 const components::ComponentContext& component_context);
123
124} // namespace testsuite
125
126USERVER_NAMESPACE_END