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