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/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, {})