blob: 07bd8793bc53a26b5a6c32fc7c5b739dfc1bce44 [file] [log] [blame]
Danil Chapovalove7b48a12023-11-22 15:01:341/*
2 * Copyright (c) 2023 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "api/environment/environment.h"
12
13#include <memory>
14#include <string>
15#include <utility>
16#include <vector>
17
18#include "absl/functional/any_invocable.h"
19#include "absl/types/optional.h"
20#include "api/environment/environment_factory.h"
21#include "api/field_trials_view.h"
22#include "api/rtc_event_log/rtc_event_log.h"
23#include "api/task_queue/task_queue_factory.h"
24#include "api/units/timestamp.h"
25#include "system_wrappers/include/clock.h"
26#include "test/gmock.h"
27#include "test/gtest.h"
28
29namespace webrtc {
30namespace {
31
32using ::testing::ElementsAre;
33using ::testing::IsEmpty;
34using ::testing::Not;
35using ::testing::NotNull;
36using ::testing::Ref;
37
38class FakeEvent : public RtcEvent {
39 public:
40 Type GetType() const override { return RtcEvent::Type::FakeEvent; }
41 bool IsConfigEvent() const override { return false; }
42};
43
44class FakeFieldTrials : public FieldTrialsView {
45 public:
46 explicit FakeFieldTrials(absl::AnyInvocable<void() &&> on_destroyed = nullptr)
47 : on_destroyed_(std::move(on_destroyed)) {}
48 ~FakeFieldTrials() override {
49 if (on_destroyed_ != nullptr) {
50 std::move(on_destroyed_)();
51 }
52 }
53
54 std::string Lookup(absl::string_view key) const override { return "fake"; }
55
56 private:
57 absl::AnyInvocable<void() &&> on_destroyed_;
58};
59
60class FakeTaskQueueFactory : public TaskQueueFactory {
61 public:
62 explicit FakeTaskQueueFactory(
63 absl::AnyInvocable<void() &&> on_destroyed = nullptr)
64 : on_destroyed_(std::move(on_destroyed)) {}
65 ~FakeTaskQueueFactory() override {
66 if (on_destroyed_ != nullptr) {
67 std::move(on_destroyed_)();
68 }
69 }
70
71 std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
72 absl::string_view name,
73 Priority priority) const override {
74 return nullptr;
75 }
76
77 private:
78 absl::AnyInvocable<void() &&> on_destroyed_;
79};
80
81TEST(EnvironmentTest, DefaultEnvironmentHasAllUtilities) {
82 Environment env = EnvironmentFactory().Create();
83
84 // Try to use each utility, expect no crashes.
85 env.clock().CurrentTime();
86 EXPECT_THAT(env.task_queue_factory().CreateTaskQueue(
87 "test", TaskQueueFactory::Priority::NORMAL),
88 NotNull());
89 env.event_log().Log(std::make_unique<FakeEvent>());
90 env.field_trials().Lookup("WebRTC-Debugging-RtpDump");
91}
92
93TEST(EnvironmentTest, UsesProvidedUtilitiesWithOwnership) {
94 auto owned_field_trials = std::make_unique<FakeFieldTrials>();
95 auto owned_task_queue_factory = std::make_unique<FakeTaskQueueFactory>();
96 auto owned_clock = std::make_unique<SimulatedClock>(Timestamp::Zero());
97 auto owned_event_log = std::make_unique<RtcEventLogNull>();
98
99 FieldTrialsView& field_trials = *owned_field_trials;
100 TaskQueueFactory& task_queue_factory = *owned_task_queue_factory;
101 Clock& clock = *owned_clock;
102 RtcEventLog& event_log = *owned_event_log;
103
104 Environment env = CreateEnvironment(
105 std::move(owned_field_trials), std::move(owned_clock),
106 std::move(owned_task_queue_factory), std::move(owned_event_log));
107
108 EXPECT_THAT(env.field_trials(), Ref(field_trials));
109 EXPECT_THAT(env.task_queue_factory(), Ref(task_queue_factory));
110 EXPECT_THAT(env.clock(), Ref(clock));
111 EXPECT_THAT(env.event_log(), Ref(event_log));
112}
113
114TEST(EnvironmentTest, UsesProvidedUtilitiesWithoutOwnership) {
115 FakeFieldTrials field_trials;
116 FakeTaskQueueFactory task_queue_factory;
117 SimulatedClock clock(Timestamp::Zero());
118 RtcEventLogNull event_log;
119
120 Environment env =
121 CreateEnvironment(&field_trials, &clock, &task_queue_factory, &event_log);
122
123 EXPECT_THAT(env.field_trials(), Ref(field_trials));
124 EXPECT_THAT(env.task_queue_factory(), Ref(task_queue_factory));
125 EXPECT_THAT(env.clock(), Ref(clock));
126 EXPECT_THAT(env.event_log(), Ref(event_log));
127}
128
129TEST(EnvironmentTest, UsesLastProvidedUtility) {
130 auto owned_field_trials1 = std::make_unique<FakeFieldTrials>();
131 auto owned_field_trials2 = std::make_unique<FakeFieldTrials>();
132 FieldTrialsView& field_trials2 = *owned_field_trials2;
133
134 Environment env = CreateEnvironment(std::move(owned_field_trials1),
135 std::move(owned_field_trials2));
136
137 EXPECT_THAT(env.field_trials(), Ref(field_trials2));
138}
139
140// Utilities can be provided from different sources, and when some source
141// choose not to provide an utility, it is usually expressed with nullptr.
142// When utility is not provided, it is natural to use previously set one.
143// E.g. Both PeerConnectionFactoryDependencies and PeerConnectionDependencies
144// provide field trials. When PeerConnectionDependencies::trials == nullptr,
145// then trials from the PeerConnectionFactoryDependencies should be used.
146// With nullptr accepted and ignored this can be expressed by
147// `Environemt env = CreateEnvironment(pcf_deps.trials, pc_deps.trials);`
148// That would use pc_deps.trials when not nullptr, pcf_deps.trials when
149// pc_deps.trials is nullptr, but pcf_deps.trials is not, and default field
150// trials when both are nullptr.
151TEST(EnvironmentTest, IgnoresProvidedNullptrUtility) {
152 auto owned_field_trials = std::make_unique<FakeFieldTrials>();
153 std::unique_ptr<FieldTrialsView> null_field_trials = nullptr;
154 FieldTrialsView& field_trials = *owned_field_trials;
155
156 Environment env = CreateEnvironment(std::move(owned_field_trials),
157 std::move(null_field_trials));
158
159 EXPECT_THAT(env.field_trials(), Ref(field_trials));
160}
161
162TEST(EnvironmentTest, KeepsUtilityAliveWhileEnvironmentIsAlive) {
163 bool utility_destroyed = false;
164 auto field_trials = std::make_unique<FakeFieldTrials>(
165 /*on_destroyed=*/[&] { utility_destroyed = true; });
166
167 // Wrap Environment into optional to have explicit control when it is deleted.
168 absl::optional<Environment> env = CreateEnvironment(std::move(field_trials));
169
170 EXPECT_FALSE(utility_destroyed);
171 env = absl::nullopt;
172 EXPECT_TRUE(utility_destroyed);
173}
174
175TEST(EnvironmentTest, KeepsUtilityAliveWhileCopyOfEnvironmentIsAlive) {
176 bool utility_destroyed = false;
177 auto field_trials = std::make_unique<FakeFieldTrials>(
178 /*on_destroyed=*/[&] { utility_destroyed = true; });
179
180 absl::optional<Environment> env1 = CreateEnvironment(std::move(field_trials));
181 absl::optional<Environment> env2 = env1;
182
183 EXPECT_FALSE(utility_destroyed);
184 env1 = absl::nullopt;
185 EXPECT_FALSE(utility_destroyed);
186 env2 = absl::nullopt;
187 EXPECT_TRUE(utility_destroyed);
188}
189
190TEST(EnvironmentTest, FactoryCanBeReusedToCreateDifferentEnvironments) {
191 auto owned_task_queue_factory = std::make_unique<FakeTaskQueueFactory>();
192 auto owned_field_trials1 = std::make_unique<FakeFieldTrials>();
193 auto owned_field_trials2 = std::make_unique<FakeFieldTrials>();
194 TaskQueueFactory& task_queue_factory = *owned_task_queue_factory;
195 FieldTrialsView& field_trials1 = *owned_field_trials1;
196 FieldTrialsView& field_trials2 = *owned_field_trials2;
197
198 EnvironmentFactory factory;
199 factory.Set(std::move(owned_task_queue_factory));
200 factory.Set(std::move(owned_field_trials1));
201 Environment env1 = factory.Create();
202 factory.Set(std::move(owned_field_trials2));
203 Environment env2 = factory.Create();
204
205 // Environments share the same custom task queue factory.
206 EXPECT_THAT(env1.task_queue_factory(), Ref(task_queue_factory));
207 EXPECT_THAT(env2.task_queue_factory(), Ref(task_queue_factory));
208
209 // Environments have different field trials.
210 EXPECT_THAT(env1.field_trials(), Ref(field_trials1));
211 EXPECT_THAT(env2.field_trials(), Ref(field_trials2));
212}
213
214TEST(EnvironmentTest, FactoryCanCreateNewEnvironmentFromExistingOne) {
215 Environment env1 =
216 CreateEnvironment(std::make_unique<FakeTaskQueueFactory>());
217 EnvironmentFactory factory(env1);
218 factory.Set(std::make_unique<FakeFieldTrials>());
219 Environment env2 = factory.Create();
220
221 // Environments share the same default clock.
222 EXPECT_THAT(env2.clock(), Ref(env1.clock()));
223
224 // Environments share the same custom task queue factory.
225 EXPECT_THAT(env2.task_queue_factory(), Ref(env1.task_queue_factory()));
226
227 // Environments have different field trials.
228 EXPECT_THAT(env2.field_trials(), Not(Ref(env1.field_trials())));
229}
230
231TEST(EnvironmentTest, KeepsOwnershipsWhenCreateNewEnvironmentFromExistingOne) {
232 bool utility1_destroyed = false;
233 bool utility2_destroyed = false;
234 absl::optional<Environment> env1 =
235 CreateEnvironment(std::make_unique<FakeTaskQueueFactory>(
236 /*on_destroyed=*/[&] { utility1_destroyed = true; }));
237
238 absl::optional<EnvironmentFactory> factory = EnvironmentFactory(*env1);
239
240 // Destroy env1, check utility1 it was using is still alive.
241 env1 = absl::nullopt;
242 EXPECT_FALSE(utility1_destroyed);
243
244 factory->Set(std::make_unique<FakeFieldTrials>(
245 /*on_destroyed=*/[&] { utility2_destroyed = true; }));
246 absl::optional<Environment> env2 = factory->Create();
247
248 // Destroy the factory, check all utilities used by env2 are alive.
249 factory = absl::nullopt;
250 EXPECT_FALSE(utility1_destroyed);
251 EXPECT_FALSE(utility2_destroyed);
252
253 // Once last Environment object is deleted, utilties should be deleted too.
254 env2 = absl::nullopt;
255 EXPECT_TRUE(utility1_destroyed);
256 EXPECT_TRUE(utility2_destroyed);
257}
258
259TEST(EnvironmentTest, DestroysUtilitiesInReverseProvidedOrder) {
260 std::vector<std::string> destroyed;
261 auto field_trials = std::make_unique<FakeFieldTrials>(
262 /*on_destroyed=*/[&] { destroyed.push_back("field_trials"); });
263 auto task_queue_factory = std::make_unique<FakeTaskQueueFactory>(
264 /*on_destroyed=*/[&] { destroyed.push_back("task_queue_factory"); });
265
266 absl::optional<Environment> env =
267 CreateEnvironment(std::move(field_trials), std::move(task_queue_factory));
268
269 ASSERT_THAT(destroyed, IsEmpty());
270 env = absl::nullopt;
271 EXPECT_THAT(destroyed, ElementsAre("task_queue_factory", "field_trials"));
272}
273
274} // namespace
275} // namespace webrtc