Skip to content

Commit 9b3b567

Browse files
committed
cc core: add a test that OnAllComponentsAreStopping is called in the documented order
See @ref components::ServiceLifetimeStage for docs of the order in which callbacks are called. This PR changes neither the order nor the docs. commit_hash:75aeb6380f6aa1c2b0ca1d8fcbd85deb5ff1a27a
1 parent 8b57202 commit 9b3b567

File tree

3 files changed

+119
-9
lines changed

3 files changed

+119
-9
lines changed

.mapping.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,7 @@
12961296
"core/src/components/component_context_impl.cpp":"taxi/uservices/userver/core/src/components/component_context_impl.cpp",
12971297
"core/src/components/component_context_impl.hpp":"taxi/uservices/userver/core/src/components/component_context_impl.hpp",
12981298
"core/src/components/component_fwd.cpp":"taxi/uservices/userver/core/src/components/component_fwd.cpp",
1299+
"core/src/components/component_lifecycle_test.cpp":"taxi/uservices/userver/core/src/components/component_lifecycle_test.cpp",
12991300
"core/src/components/component_list.cpp":"taxi/uservices/userver/core/src/components/component_list.cpp",
13001301
"core/src/components/component_list_test.cpp":"taxi/uservices/userver/core/src/components/component_list_test.cpp",
13011302
"core/src/components/component_list_test.hpp":"taxi/uservices/userver/core/src/components/component_list_test.hpp",
@@ -1325,8 +1326,8 @@
13251326
"core/src/components/minimal_server_component_list_test.cpp":"taxi/uservices/userver/core/src/components/minimal_server_component_list_test.cpp",
13261327
"core/src/components/process_starter.cpp":"taxi/uservices/userver/core/src/components/process_starter.cpp",
13271328
"core/src/components/process_starter.yaml":"taxi/uservices/userver/core/src/components/process_starter.yaml",
1328-
"core/src/components/resource_scope_test.cpp":"taxi/uservices/userver/core/src/components/resource_scope_test.cpp",
13291329
"core/src/components/run.cpp":"taxi/uservices/userver/core/src/components/run.cpp",
1330+
"core/src/components/scope_test.cpp":"taxi/uservices/userver/core/src/components/scope_test.cpp",
13301331
"core/src/components/single_threaded_task_processors.cpp":"taxi/uservices/userver/core/src/components/single_threaded_task_processors.cpp",
13311332
"core/src/components/single_threaded_task_processors.yaml":"taxi/uservices/userver/core/src/components/single_threaded_task_processors.yaml",
13321333
"core/src/components/state.cpp":"taxi/uservices/userver/core/src/components/state.cpp",
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <userver/components/component_base.hpp>
4+
#include <userver/components/component_context.hpp>
5+
#include <userver/components/minimal_component_list.hpp>
6+
#include <userver/components/run.hpp>
7+
8+
#include <components/component_list_test.hpp>
9+
10+
USERVER_NAMESPACE_BEGIN
11+
12+
namespace {
13+
14+
std::atomic<bool> good_component_constructed{false};
15+
std::atomic<bool> good_component_on_all_components_loaded_called{false};
16+
std::atomic<bool> good_component_on_all_components_stopping_called{false};
17+
std::atomic<bool> bad_component_construction_started{false};
18+
19+
class GoodComponent final : public components::ComponentBase {
20+
public:
21+
static constexpr std::string_view kName = "good-component";
22+
23+
GoodComponent(const components::ComponentConfig& config, const components::ComponentContext& context)
24+
: ComponentBase(config, context)
25+
{
26+
good_component_constructed = true;
27+
}
28+
29+
void OnAllComponentsLoaded() override { good_component_on_all_components_loaded_called = true; }
30+
31+
void OnAllComponentsAreStopping() override { good_component_on_all_components_stopping_called = true; }
32+
};
33+
34+
class BadComponent final : public components::ComponentBase {
35+
public:
36+
static constexpr std::string_view kName = "bad-component";
37+
38+
BadComponent(const components::ComponentConfig& config, const components::ComponentContext& context)
39+
: ComponentBase(config, context)
40+
{
41+
[[maybe_unused]] auto& good_component = context.FindComponent<GoodComponent>();
42+
bad_component_construction_started = true;
43+
throw std::runtime_error("BadComponent constructor intentionally throws");
44+
}
45+
};
46+
47+
} // namespace
48+
49+
TEST(ComponentLifecycle, OnAllComponentsAreStoppingCalledWhenConstructorThrows) {
50+
// Reset static variables for --gtest_repeat.
51+
good_component_constructed = false;
52+
good_component_on_all_components_loaded_called = false;
53+
good_component_on_all_components_stopping_called = false;
54+
bad_component_construction_started = false;
55+
56+
const std::string config = tests::MergeYaml(
57+
tests::kMinimalStaticConfig,
58+
R"(
59+
components_manager:
60+
components:
61+
logging:
62+
fs-task-processor: main-task-processor
63+
loggers:
64+
default:
65+
file_path: '@null'
66+
format: ltsv
67+
good-component: {}
68+
bad-component: {}
69+
)"
70+
);
71+
72+
UEXPECT_THROW_MSG(
73+
components::RunOnce(
74+
components::InMemoryConfig{config},
75+
components::MinimalComponentList().Append<GoodComponent>().Append<BadComponent>()
76+
),
77+
std::runtime_error,
78+
"BadComponent constructor intentionally throws"
79+
);
80+
81+
EXPECT_TRUE(good_component_constructed);
82+
EXPECT_TRUE(bad_component_construction_started);
83+
EXPECT_FALSE(good_component_on_all_components_loaded_called);
84+
EXPECT_TRUE(good_component_on_all_components_stopping_called);
85+
}
86+
87+
USERVER_NAMESPACE_END

core/src/components/resource_scope_test.cpp renamed to core/src/components/scope_test.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
#include <userver/utest/utest.hpp>
1+
#include <gmock/gmock.h>
22

33
#include <userver/components/component_base.hpp>
44
#include <userver/components/component_context.hpp>
55
#include <userver/components/minimal_component_list.hpp>
66
#include <userver/components/run.hpp>
77
#include <userver/components/scope.hpp>
88
#include <userver/logging/log.hpp>
9+
#include <userver/utest/utest.hpp>
910
#include <userver/utils/fast_scope_guard.hpp>
1011

1112
USERVER_NAMESPACE_BEGIN
@@ -34,8 +35,12 @@ const std::string kConfig = R"(
3435

3536
TEST(ComponentsScope, Smoke)
3637
{
37-
static bool init_called = false;
38-
static bool destroy_called = false;
38+
static bool init_called{};
39+
static bool destroy_called{};
40+
41+
// Reset static variables for --gtest_repeat.
42+
init_called = false;
43+
destroy_called = false;
3944

4045
class ComponentWithResource final : public components::ComponentBase {
4146
public:
@@ -60,6 +65,9 @@ TEST(ComponentsScope, HappyPathOrder)
6065
{
6166
static std::vector<int> trace;
6267

68+
// Reset static variables for --gtest_repeat.
69+
trace = {};
70+
6371
class ComponentWithResource final : public components::ComponentBase {
6472
public:
6573
ComponentWithResource(const components::ComponentConfig& config, const components::ComponentContext& context)
@@ -82,13 +90,16 @@ TEST(ComponentsScope, HappyPathOrder)
8290
auto component_list = components::MinimalComponentList().Append<ComponentWithResource>("component");
8391
components::RunOnce(components::InMemoryConfig{kConfig}, component_list);
8492

85-
EXPECT_EQ(trace, (std::vector{0, 1, 3, 4, 2}));
93+
EXPECT_THAT(trace, ::testing::ElementsAre(0, 1, 3, 4, 2));
8694
}
8795

8896
TEST(ComponentsScope, CtrThrow)
8997
{
9098
static std::vector<int> trace;
9199

100+
// Reset static variables for --gtest_repeat.
101+
trace = {};
102+
92103
class ComponentWithResource final : public components::ComponentBase {
93104
public:
94105
ComponentWithResource(const components::ComponentConfig& config, const components::ComponentContext& context)
@@ -111,15 +122,22 @@ TEST(ComponentsScope, CtrThrow)
111122
};
112123

113124
auto component_list = components::MinimalComponentList().Append<ComponentWithResource>("component");
114-
EXPECT_THROW(components::RunOnce(components::InMemoryConfig{kConfig}, component_list), std::runtime_error);
125+
UEXPECT_THROW_MSG(
126+
components::RunOnce(components::InMemoryConfig{kConfig}, component_list),
127+
std::runtime_error,
128+
"1"
129+
);
115130

116-
EXPECT_EQ(trace, (std::vector{0}));
131+
EXPECT_THAT(trace, ::testing::ElementsAre(0));
117132
}
118133

119134
TEST(ComponentsScope, CallbackThrow)
120135
{
121136
static std::vector<int> trace;
122137

138+
// Reset static variables for --gtest_repeat.
139+
trace = {};
140+
123141
class ComponentWithResource final : public components::ComponentBase {
124142
public:
125143
ComponentWithResource(const components::ComponentConfig& config, const components::ComponentContext& context)
@@ -141,9 +159,13 @@ TEST(ComponentsScope, CallbackThrow)
141159
};
142160

143161
auto component_list = components::MinimalComponentList().Append<ComponentWithResource>("component");
144-
EXPECT_THROW(components::RunOnce(components::InMemoryConfig{kConfig}, component_list), std::runtime_error);
162+
UEXPECT_THROW_MSG(
163+
components::RunOnce(components::InMemoryConfig{kConfig}, component_list),
164+
std::runtime_error,
165+
"1"
166+
);
145167

146-
EXPECT_EQ(trace, (std::vector{0, 1, 3, 2}));
168+
EXPECT_THAT(trace, ::testing::ElementsAre(0, 1, 3, 2));
147169
}
148170

149171
USERVER_NAMESPACE_END

0 commit comments

Comments
 (0)