userver: userver/testsuite/testpoint.hpp Source File
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/serialize.hpp>
10#include <userver/formats/json/value.hpp>
11#include <userver/utils/function_ref.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace testsuite {
16
17/// @brief Returns true if testpoints are available in runtime.
18bool AreTestpointsAvailable() noexcept;
19
20using TestpointCallback = utils::function_ref<void(const formats::json::Value&)>;
21
22} // namespace testsuite
23
24namespace testsuite::impl {
25
26bool IsTestpointEnabled(std::string_view name) noexcept;
27
28void ExecuteTestpointCoro(std::string_view name, const formats::json::Value& json, TestpointCallback callback);
29
30void ExecuteTestpointBlocking(
31 std::string_view name,
32 const formats::json::Value& json,
33 TestpointCallback callback,
34 engine::TaskProcessor& task_processor
35);
36
37void DoNothing(const formats::json::Value&) noexcept;
38
39} // namespace testsuite::impl
40
41USERVER_NAMESPACE_END
42
43// clang-format off
44
45/// @brief Send testpoint notification and receive data. Works only if
46/// testpoint support is enabled (e.g. in components::TestsControl),
47/// otherwise does nothing.
48///
49/// Example usage:
50/// @snippet samples/testsuite-support/src/testpoint.cpp Sample TESTPOINT_CALLBACK usage cpp
51/// @snippet samples/testsuite-support/tests/test_testpoint.py Sample TESTPOINT_CALLBACK usage python
52///
53/// Throws nothing if server::handlers::TestsControl is not
54/// loaded or it is disabled in static config via `load-enabled: false`.
55///
56/// @hideinitializer
57
58// clang-format on
59// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
60#define TESTPOINT_CALLBACK(name, json, callback)
61 do {
62 if (__builtin_expect(!USERVER_NAMESPACE::testsuite::AreTestpointsAvailable(), true)) break;
63
64 /* cold testing path: */
65 const auto& userver_impl_tp_name = name;
66 if (!USERVER_NAMESPACE::testsuite::impl::IsTestpointEnabled(userver_impl_tp_name)) break;
67
68 USERVER_NAMESPACE::testsuite::impl::ExecuteTestpointCoro(userver_impl_tp_name, json, callback);
69 } while (false)
70
71// clang-format off
72
73/// @brief Send testpoint notification. Works only if testpoint support is
74/// enabled (e.g. in components::TestsControl), otherwise does nothing.
75///
76/// Example usage:
77/// @snippet samples/testsuite-support/src/testpoint.cpp Testpoint - TESTPOINT()
78/// @snippet samples/testsuite-support/tests/test_testpoint.py Testpoint - fixture
79///
80/// Throws nothing if server::handlers::TestsControl is not
81/// loaded or it is disabled in static config via `load-enabled: false`.
82///
83/// @hideinitializer
84
85// clang-format on
86// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
87#define TESTPOINT(name, json) TESTPOINT_CALLBACK(name, json, USERVER_NAMESPACE::testsuite::impl::DoNothing)
88
89/// @brief Same as `TESTPOINT_CALLBACK` but must be called outside of
90/// coroutine (e.g. from std::thread routine).
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// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
97#define TESTPOINT_CALLBACK_NONCORO(name, json, task_processor, callback)
98 do {
99 if (__builtin_expect(!USERVER_NAMESPACE::testsuite::AreTestpointsAvailable(), true)) break;
100
101 /* cold testing path: */
102 const auto& userver_impl_tp_name = name;
103 if (!USERVER_NAMESPACE::testsuite::impl::IsTestpointEnabled(userver_impl_tp_name)) break;
104
105 USERVER_NAMESPACE::testsuite::impl::ExecuteTestpointBlocking(
106 userver_impl_tp_name, json, callback, task_processor
107 );
108 } while (false)
109
110/// @brief Same as `TESTPOINT` but must be called outside of
111/// coroutine (e.g. from std::thread routine).
112///
113/// Throws nothing if server::handlers::TestsControl is not
114/// loaded or it is disabled in static config via `load-enabled: false`.
115///
116/// @hideinitializer
117// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
118#define TESTPOINT_NONCORO(name, json, task_processor)
119 TESTPOINT_CALLBACK_NONCORO(name, json, task_processor, USERVER_NAMESPACE::testsuite::impl::DoNothing)