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