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/testsuite/testpoint_control.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::impl {
22
23class TestpointScope final {
24 public:
25 TestpointScope();
26 ~TestpointScope();
27
28 explicit operator bool() const noexcept;
29
30 // The returned client must only be used within Scope's lifetime
31 const TestpointClientBase& GetClient() const noexcept;
32
33 private:
34 struct Impl;
35 utils::FastPimpl<Impl, 24, 8> impl_;
36};
37
38bool IsTestpointEnabled(std::string_view name);
39
40void ExecuteTestpointBlocking(const std::string& name,
41 const formats::json::Value& json,
42 const TestpointClientBase::Callback& callback,
43 engine::TaskProcessor& task_processor);
44
45} // namespace testsuite::impl
46
47USERVER_NAMESPACE_END
48
49// clang-format off
50
51/// @brief Send testpoint notification and receive data. Works only if
52/// testpoint support is enabled (e.g. in components::TestsControl),
53/// otherwise does nothing.
54///
55/// Example usage:
56/// @snippet samples/testsuite-support/src/testpoint.cpp Sample TESTPOINT_CALLBACK usage cpp
57/// @snippet samples/testsuite-support/tests/test_testpoint.py Sample TESTPOINT_CALLBACK usage python
58///
59/// @hideinitializer
60
61// clang-format on
62// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
63#define TESTPOINT_CALLBACK(name, json, callback)
64 do {
65 namespace tp = USERVER_NAMESPACE::testsuite::impl;
66 if (!tp::IsTestpointEnabled(name)) break;
67 const tp::TestpointScope tp_scope;
68 if (!tp_scope) break;
69 /* only evaluate 'json' if actually needed */
70 tp_scope.GetClient().Execute(name, json, callback);
71 } while (false)
72
73// clang-format off
74
75/// @brief Send testpoint notification. Works only if testpoint support is
76/// enabled (e.g. in components::TestsControl), otherwise does nothing.
77///
78/// Example usage:
79/// @snippet samples/testsuite-support/src/testpoint.cpp Testpoint - TESTPOINT()
80/// @snippet samples/testsuite-support/tests/test_testpoint.py Testpoint - fixture
81///
82/// @hideinitializer
83
84// clang-format on
85// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
86#define TESTPOINT(name, json) TESTPOINT_CALLBACK(name, json, {})
87
88/// @brief Same as `TESTPOINT_CALLBACK` but must be called outside of
89/// coroutine (e.g. from std::thread routine).
90///
91/// @hideinitializer
92// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
93#define TESTPOINT_CALLBACK_NONCORO(name, json, task_processor, callback)
94 do {
95 namespace tp = USERVER_NAMESPACE::testsuite::impl;
96 if (!tp::IsTestpointEnabled(name)) break;
97 tp::ExecuteTestpointBlocking(name, json, callback, task_processor);
98 } while (false)
99
100/// @brief Same as `TESTPOINT` but must be called outside of
101/// coroutine (e.g. from std::thread routine).
102///
103/// @hideinitializer
104// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
105#define TESTPOINT_NONCORO(name, json, task_processor)
106 TESTPOINT_CALLBACK_NONCORO(name, json, task_processor, {})