userver: userver/testsuite/testpoint.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
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)