userver: userver/testsuite/testpoint.hpp Source File
Loading...
Searching...
No Matches
testpoint.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/testsuite/testpoint.hpp
4/// @brief @copybrief TESTPOINT
5
6#include <string>
7
8#include <userver/engine/task/task_processor_fwd.hpp>
9#include <userver/formats/json/value.hpp>
10#include <userver/utils/function_ref.hpp>
11
12// TODO remove extra includes
13#include <fmt/format.h>
14#include <atomic>
15#include <chrono>
16#include <userver/rcu/rcu.hpp>
17#include <userver/utils/async.hpp>
18
19USERVER_NAMESPACE_BEGIN
20
21namespace testsuite {
22
23/// @brief Returns true if testpoints are available in runtime.
24bool AreTestpointsAvailable() noexcept;
25
27 utils::function_ref<void(const formats::json::Value&)>;
28
29} // namespace testsuite
30
31namespace testsuite::impl {
32
33bool IsTestpointEnabled(std::string_view name) noexcept;
34
35void ExecuteTestpointCoro(std::string_view name,
36 const formats::json::Value& json,
37 TestpointCallback callback);
38
39void ExecuteTestpointBlocking(std::string_view name,
40 const formats::json::Value& json,
41 TestpointCallback callback,
42 engine::TaskProcessor& task_processor);
43
44void DoNothing(const formats::json::Value&) noexcept;
45
46} // namespace testsuite::impl
47
48USERVER_NAMESPACE_END
49
50// clang-format off
51
52/// @brief Send testpoint notification and receive data. Works only if
53/// testpoint support is enabled (e.g. in components::TestsControl),
54/// otherwise does nothing.
55///
56/// Example usage:
57/// @snippet samples/testsuite-support/src/testpoint.cpp Sample TESTPOINT_CALLBACK usage cpp
58/// @snippet samples/testsuite-support/tests/test_testpoint.py Sample TESTPOINT_CALLBACK usage python
59///
60/// Throws nothing if server::handlers::TestsControl is not
61/// loaded or it is disabled in static config via `load-enabled: false`.
62///
63/// @hideinitializer
64
65// clang-format on
66// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
67#define TESTPOINT_CALLBACK(name, json, callback)
68 do {
69 if (__builtin_expect(
70 !USERVER_NAMESPACE::testsuite::AreTestpointsAvailable(), true))
71 break;
72
73 /* cold testing path: */
74 const auto& userver_impl_tp_name = name;
75 if (!USERVER_NAMESPACE::testsuite::impl::IsTestpointEnabled(
76 userver_impl_tp_name))
77 break;
78
79 USERVER_NAMESPACE::testsuite::impl::ExecuteTestpointCoro(
80 userver_impl_tp_name, json, callback);
81 } while (false)
82
83// clang-format off
84
85/// @brief Send testpoint notification. Works only if testpoint support is
86/// enabled (e.g. in components::TestsControl), otherwise does nothing.
87///
88/// Example usage:
89/// @snippet samples/testsuite-support/src/testpoint.cpp Testpoint - TESTPOINT()
90/// @snippet samples/testsuite-support/tests/test_testpoint.py Testpoint - fixture
91///
92/// Throws nothing if server::handlers::TestsControl is not
93/// loaded or it is disabled in static config via `load-enabled: false`.
94///
95/// @hideinitializer
96
97// clang-format on
98// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
99#define TESTPOINT(name, json)
100 TESTPOINT_CALLBACK(name, json, USERVER_NAMESPACE::testsuite::impl::DoNothing)
101
102/// @brief Same as `TESTPOINT_CALLBACK` but must be called outside of
103/// coroutine (e.g. from std::thread routine).
104///
105/// Throws nothing if server::handlers::TestsControl is not
106/// loaded or it is disabled in static config via `load-enabled: false`.
107///
108/// @hideinitializer
109// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
110#define TESTPOINT_CALLBACK_NONCORO(name, json, task_processor, callback)
111 do {
112 if (__builtin_expect(
113 !USERVER_NAMESPACE::testsuite::AreTestpointsAvailable(), true))
114 break;
115
116 /* cold testing path: */
117 const auto& userver_impl_tp_name = name;
118 if (!USERVER_NAMESPACE::testsuite::impl::IsTestpointEnabled(
119 userver_impl_tp_name))
120 break;
121
122 USERVER_NAMESPACE::testsuite::impl::ExecuteTestpointBlocking(
123 userver_impl_tp_name, json, callback, task_processor);
124 } while (false)
125
126/// @brief Same as `TESTPOINT` but must be called outside of
127/// coroutine (e.g. from std::thread routine).
128///
129/// Throws nothing if server::handlers::TestsControl is not
130/// loaded or it is disabled in static config via `load-enabled: false`.
131///
132/// @hideinitializer
133// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
134#define TESTPOINT_NONCORO(name, json, task_processor)
135 TESTPOINT_CALLBACK_NONCORO(name, json, task_processor,
136 USERVER_NAMESPACE::testsuite::impl::DoNothing)