Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,63 @@
# Copyright (c) 2023 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("../../webrtc.gni")
rtc_source_set("environment") {
visibility = [ "*" ]
sources = [ "environment.h" ]
deps = [
"..:refcountedbase",
"..:scoped_refptr",
"../../rtc_base/system:rtc_export",
]
absl_deps = [ "//third_party/abseil-cpp/absl/base:nullability" ]
}
rtc_library("environment_factory") {
visibility = [ "*" ]
poisonous = [ "environment_construction" ]
sources = [
"environment_factory.cc",
"environment_factory.h",
]
deps = [
":environment",
"..:make_ref_counted",
"..:refcountedbase",
"..:scoped_refptr",
"../../rtc_base:checks",
"../../rtc_base/system:rtc_export",
"../../system_wrappers",
"../rtc_event_log",
"../task_queue:default_task_queue_factory",
"../transport:field_trial_based_config",
]
absl_deps = [ "//third_party/abseil-cpp/absl/base:nullability" ]
}
if (rtc_include_tests) {
rtc_library("environment_unittests") {
testonly = true
sources = [ "environment_unittest.cc" ]
deps = [
":environment",
":environment_factory",
"..:field_trials_view",
"../../system_wrappers",
"../../test:test_support",
"../rtc_event_log",
"../task_queue",
"../units:timestamp",
]
absl_deps = [
"//third_party/abseil-cpp/absl/functional:any_invocable",
"//third_party/abseil-cpp/absl/types:optional",
]
}
}

View file

@ -0,0 +1,15 @@
# Environment has a limited visibility for stronger control what utilities are
# exposed through it.
# Utilities exposed through environemnt
# - should be helpful for various WebRTC sub components.
# - should be thread safe.
# - should have a default implementation.
# - should provide functionality different to existing utilities in the
# environemnt.
# - should need at most one instance per peer connection.
set noparent
include ../../OWNERS_INFRA
danilchap@webrtc.org
hta@webrtc.org
mbonadei@webrtc.org

View file

@ -0,0 +1,148 @@
/*
* Copyright 2023 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// This header file provides wrapper for common WebRTC utilities.
// Different application may need different implementations of these utilities,
// Moreover, single application may need to use WebRTC for multiple purposes,
// and thus would need to provide different utilities implementations for
// different peer connections.
// The main purpose of the `Environment` class below is to propagate references
// to those utilities to all WebRTC classes that need them.
#ifndef API_ENVIRONMENT_ENVIRONMENT_H_
#define API_ENVIRONMENT_ENVIRONMENT_H_
#include <utility>
#include "absl/base/nullability.h"
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// These classes are forward declared to keep Environment dependencies
// lightweight. Users who need any of the types below should include their
// header explicitely.
class Clock;
class TaskQueueFactory;
class FieldTrialsView;
class RtcEventLog;
// Contains references to WebRTC utilities. Object of this class should be
// passed as a construction parameter and saved by value in each class that
// needs it. Most classes shouldn't create a new instance of the `Environment`,
// but instead should use a propagated copy.
// Usually Environment should be the first parameter in a constructor or a
// factory, and the first member in the class. Keeping Environment as the first
// member in the class ensures utilities (e.g. clock) are still valid during
// destruction of other members.
//
// Example:
// class PeerConnection {
// public:
// PeerConnection(const Environment& env, ...)
// : env_(env),
// log_duration_on_destruction_(&env_.clock()),
// rtp_manager_(env_, ...),
// ...
//
// const FieldTrialsView& trials() const { return env_.field_trials(); }
//
// scoped_refptr<RtpTransceiverInterface> AddTransceiver(...) {
// return make_ref_counted<RtpTransceiverImpl>(env_, ...);
// }
//
// private:
// const Environment env_;
// Stats log_duration_on_destruction_;
// RtpTransmissionManager rtp_manager_;
// };
// This class is thread safe.
class RTC_EXPORT Environment final {
public:
// Default constructor is deleted in favor of creating this object using
// `EnvironmentFactory`. To create the default environment use
// `EnvironmentFactory().Create()` or `CreateEnvironment()`.
Environment() = delete;
Environment(const Environment&) = default;
Environment(Environment&&) = default;
Environment& operator=(const Environment&) = default;
Environment& operator=(Environment&&) = default;
~Environment() = default;
// Provides means to alter behavior, mostly for A/B testing new features.
// See ../../g3doc/field-trials.md
const FieldTrialsView& field_trials() const;
// Provides an interface to query current time.
// See ../../g3doc/implementation_basics.md#time
Clock& clock() const;
// Provides a factory for task queues, WebRTC threading primitives.
// See ../../g3doc/implementation_basics.md#threads
TaskQueueFactory& task_queue_factory() const;
// Provides an interface for collecting structured logs.
// See ../../logging/g3doc/rtc_event_log.md
RtcEventLog& event_log() const;
private:
friend class EnvironmentFactory;
Environment(scoped_refptr<const rtc::RefCountedBase> storage,
absl::Nonnull<const FieldTrialsView*> field_trials,
absl::Nonnull<Clock*> clock,
absl::Nonnull<TaskQueueFactory*> task_queue_factory,
absl::Nonnull<RtcEventLog*> event_log)
: storage_(std::move(storage)),
field_trials_(field_trials),
clock_(clock),
task_queue_factory_(task_queue_factory),
event_log_(event_log) {}
// Container that keeps ownership of the utilities below.
// Defining this as a RefCountedBase allows `Environment` to share this
// storage with another `Environment`, in particular allows `Environment` to
// be copyable. It is up to the `EnvironmentFactory` to provide an object that
// ensures references to utilties below are valid while object in the
// `storage_` is alive.
scoped_refptr<const rtc::RefCountedBase> storage_;
absl::Nonnull<const FieldTrialsView*> field_trials_;
absl::Nonnull<Clock*> clock_;
absl::Nonnull<TaskQueueFactory*> task_queue_factory_;
absl::Nonnull<RtcEventLog*> event_log_;
};
//------------------------------------------------------------------------------
// Implementation details follow
//------------------------------------------------------------------------------
inline const FieldTrialsView& Environment::field_trials() const {
return *field_trials_;
}
inline Clock& Environment::clock() const {
return *clock_;
}
inline TaskQueueFactory& Environment::task_queue_factory() const {
return *task_queue_factory_;
}
inline RtcEventLog& Environment::event_log() const {
return *event_log_;
}
} // namespace webrtc
#endif // API_ENVIRONMENT_ENVIRONMENT_H_

View file

@ -0,0 +1,123 @@
/*
* Copyright 2023 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/environment/environment_factory.h"
#include <memory>
#include <utility>
#include <vector>
#include "api/make_ref_counted.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "api/transport/field_trial_based_config.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
namespace {
template <typename T>
void Store(absl::Nonnull<std::unique_ptr<T>> value,
scoped_refptr<const rtc::RefCountedBase>& leaf) {
class StorageNode : public rtc::RefCountedBase {
public:
StorageNode(scoped_refptr<const rtc::RefCountedBase> parent,
absl::Nonnull<std::unique_ptr<T>> value)
: parent_(std::move(parent)), value_(std::move(value)) {}
StorageNode(const StorageNode&) = delete;
StorageNode& operator=(const StorageNode&) = delete;
~StorageNode() override = default;
private:
scoped_refptr<const rtc::RefCountedBase> parent_;
absl::Nonnull<std::unique_ptr<T>> value_;
};
// Utilities provided with ownership form a tree:
// Root is nullptr, each node keeps an ownership of one utility.
// Each child node has a link to the parent, but parent is unaware of its
// children. Each `EnvironmentFactory` and `Environment` keep a reference to a
// 'leaf_' - node with the last provided utility. This way `Environment` keeps
// ownership of a single branch of the storage tree with each used utiltity
// owned by one of the nodes on that branch.
leaf = rtc::make_ref_counted<StorageNode>(std::move(leaf), std::move(value));
}
} // namespace
EnvironmentFactory::EnvironmentFactory(const Environment& env)
: leaf_(env.storage_),
field_trials_(env.field_trials_),
clock_(env.clock_),
task_queue_factory_(env.task_queue_factory_),
event_log_(env.event_log_) {}
void EnvironmentFactory::Set(
absl::Nullable<std::unique_ptr<const FieldTrialsView>> utility) {
if (utility != nullptr) {
field_trials_ = utility.get();
Store(std::move(utility), leaf_);
}
}
void EnvironmentFactory::Set(absl::Nullable<std::unique_ptr<Clock>> utility) {
if (utility != nullptr) {
clock_ = utility.get();
Store(std::move(utility), leaf_);
}
}
void EnvironmentFactory::Set(
absl::Nullable<std::unique_ptr<TaskQueueFactory>> utility) {
if (utility != nullptr) {
task_queue_factory_ = utility.get();
Store(std::move(utility), leaf_);
}
}
void EnvironmentFactory::Set(
absl::Nullable<std::unique_ptr<RtcEventLog>> utility) {
if (utility != nullptr) {
event_log_ = utility.get();
Store(std::move(utility), leaf_);
}
}
Environment EnvironmentFactory::CreateWithDefaults() && {
if (field_trials_ == nullptr) {
Set(std::make_unique<FieldTrialBasedConfig>());
}
if (clock_ == nullptr) {
Set(Clock::GetRealTimeClock());
}
if (task_queue_factory_ == nullptr) {
Set(CreateDefaultTaskQueueFactory(field_trials_));
}
if (event_log_ == nullptr) {
Set(std::make_unique<RtcEventLogNull>());
}
RTC_DCHECK(field_trials_ != nullptr);
RTC_DCHECK(clock_ != nullptr);
RTC_DCHECK(task_queue_factory_ != nullptr);
RTC_DCHECK(event_log_ != nullptr);
return Environment(std::move(leaf_), //
field_trials_, clock_, task_queue_factory_, event_log_);
}
Environment EnvironmentFactory::Create() const {
// Create a temporary copy to avoid mutating `this` with default utilities.
return EnvironmentFactory(*this).CreateWithDefaults();
}
} // namespace webrtc

View file

@ -0,0 +1,148 @@
/*
* Copyright 2023 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_ENVIRONMENT_ENVIRONMENT_FACTORY_H_
#define API_ENVIRONMENT_ENVIRONMENT_FACTORY_H_
#include <memory>
#include <utility>
#include "absl/base/nullability.h"
#include "api/environment/environment.h"
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// These classes are forward declared to reduce amount of headers exposed
// through api header.
class Clock;
class TaskQueueFactory;
class FieldTrialsView;
class RtcEventLog;
// Constructs `Environment`.
// Individual utilities are provided using one of the `Set` functions.
// `Set` functions do nothing when nullptr value is passed.
// Creates default implementations for utilities that are not provided.
//
// Examples:
// Environment default_env = EnvironmentFactory().Create();
//
// EnvironmentFactory factory;
// factory.Set(std::make_unique<CustomTaskQueueFactory>());
// factory.Set(std::make_unique<CustomFieldTrials>());
// Environment custom_env = factory.Create();
//
class RTC_EXPORT EnvironmentFactory final {
public:
EnvironmentFactory() = default;
explicit EnvironmentFactory(const Environment& env);
EnvironmentFactory(const EnvironmentFactory&) = default;
EnvironmentFactory(EnvironmentFactory&&) = default;
EnvironmentFactory& operator=(const EnvironmentFactory&) = default;
EnvironmentFactory& operator=(EnvironmentFactory&&) = default;
~EnvironmentFactory() = default;
void Set(absl::Nullable<std::unique_ptr<const FieldTrialsView>> utility);
void Set(absl::Nullable<std::unique_ptr<Clock>> utility);
void Set(absl::Nullable<std::unique_ptr<TaskQueueFactory>> utility);
void Set(absl::Nullable<std::unique_ptr<RtcEventLog>> utility);
void Set(absl::Nullable<const FieldTrialsView*> utility);
void Set(absl::Nullable<Clock*> utility);
void Set(absl::Nullable<TaskQueueFactory*> utility);
void Set(absl::Nullable<RtcEventLog*> utility);
Environment Create() const;
private:
Environment CreateWithDefaults() &&;
scoped_refptr<const rtc::RefCountedBase> leaf_;
absl::Nullable<const FieldTrialsView*> field_trials_ = nullptr;
absl::Nullable<Clock*> clock_ = nullptr;
absl::Nullable<TaskQueueFactory*> task_queue_factory_ = nullptr;
absl::Nullable<RtcEventLog*> event_log_ = nullptr;
};
// Helper for concise way to create an environment.
// `Environment env = CreateEnvironment(utility1, utility2)` is a shortcut to
// `EnvironmentFactory factory;
// factory.Set(utility1);
// factory.Set(utility2);
// Environment env = factory.Create();`
//
// Examples:
// Environment default_env = CreateEnvironment();
// Environment custom_env =
// CreateEnvironment(std::make_unique<CustomTaskQueueFactory>(),
// std::make_unique<CustomFieldTrials>());
template <typename... Utilities>
Environment CreateEnvironment(Utilities&&... utilities);
//------------------------------------------------------------------------------
// Implementation details follow
//------------------------------------------------------------------------------
inline void EnvironmentFactory::Set(
absl::Nullable<const FieldTrialsView*> utility) {
if (utility != nullptr) {
field_trials_ = utility;
}
}
inline void EnvironmentFactory::Set(absl::Nullable<Clock*> utility) {
if (utility != nullptr) {
clock_ = utility;
}
}
inline void EnvironmentFactory::Set(absl::Nullable<TaskQueueFactory*> utility) {
if (utility != nullptr) {
task_queue_factory_ = utility;
}
}
inline void EnvironmentFactory::Set(absl::Nullable<RtcEventLog*> utility) {
if (utility != nullptr) {
event_log_ = utility;
}
}
namespace webrtc_create_environment_internal {
inline void Set(EnvironmentFactory& factory) {}
template <typename FirstUtility, typename... Utilities>
void Set(EnvironmentFactory& factory,
FirstUtility&& first,
Utilities&&... utilities) {
factory.Set(std::forward<FirstUtility>(first));
Set(factory, std::forward<Utilities>(utilities)...);
}
} // namespace webrtc_create_environment_internal
template <typename... Utilities>
Environment CreateEnvironment(Utilities&&... utilities) {
EnvironmentFactory factory;
webrtc_create_environment_internal::Set(
factory, std::forward<Utilities>(utilities)...);
return factory.Create();
}
} // namespace webrtc
#endif // API_ENVIRONMENT_ENVIRONMENT_FACTORY_H_

View file

@ -0,0 +1,275 @@
/*
* Copyright (c) 2023 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/environment/environment.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/types/optional.h"
#include "api/environment/environment_factory.h"
#include "api/field_trials_view.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/units/timestamp.h"
#include "system_wrappers/include/clock.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
using ::testing::ElementsAre;
using ::testing::IsEmpty;
using ::testing::Not;
using ::testing::NotNull;
using ::testing::Ref;
class FakeEvent : public RtcEvent {
public:
Type GetType() const override { return RtcEvent::Type::FakeEvent; }
bool IsConfigEvent() const override { return false; }
};
class FakeFieldTrials : public FieldTrialsView {
public:
explicit FakeFieldTrials(absl::AnyInvocable<void() &&> on_destroyed = nullptr)
: on_destroyed_(std::move(on_destroyed)) {}
~FakeFieldTrials() override {
if (on_destroyed_ != nullptr) {
std::move(on_destroyed_)();
}
}
std::string Lookup(absl::string_view key) const override { return "fake"; }
private:
absl::AnyInvocable<void() &&> on_destroyed_;
};
class FakeTaskQueueFactory : public TaskQueueFactory {
public:
explicit FakeTaskQueueFactory(
absl::AnyInvocable<void() &&> on_destroyed = nullptr)
: on_destroyed_(std::move(on_destroyed)) {}
~FakeTaskQueueFactory() override {
if (on_destroyed_ != nullptr) {
std::move(on_destroyed_)();
}
}
std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
absl::string_view name,
Priority priority) const override {
return nullptr;
}
private:
absl::AnyInvocable<void() &&> on_destroyed_;
};
TEST(EnvironmentTest, DefaultEnvironmentHasAllUtilities) {
Environment env = EnvironmentFactory().Create();
// Try to use each utility, expect no crashes.
env.clock().CurrentTime();
EXPECT_THAT(env.task_queue_factory().CreateTaskQueue(
"test", TaskQueueFactory::Priority::NORMAL),
NotNull());
env.event_log().Log(std::make_unique<FakeEvent>());
env.field_trials().Lookup("WebRTC-Debugging-RtpDump");
}
TEST(EnvironmentTest, UsesProvidedUtilitiesWithOwnership) {
auto owned_field_trials = std::make_unique<FakeFieldTrials>();
auto owned_task_queue_factory = std::make_unique<FakeTaskQueueFactory>();
auto owned_clock = std::make_unique<SimulatedClock>(Timestamp::Zero());
auto owned_event_log = std::make_unique<RtcEventLogNull>();
FieldTrialsView& field_trials = *owned_field_trials;
TaskQueueFactory& task_queue_factory = *owned_task_queue_factory;
Clock& clock = *owned_clock;
RtcEventLog& event_log = *owned_event_log;
Environment env = CreateEnvironment(
std::move(owned_field_trials), std::move(owned_clock),
std::move(owned_task_queue_factory), std::move(owned_event_log));
EXPECT_THAT(env.field_trials(), Ref(field_trials));
EXPECT_THAT(env.task_queue_factory(), Ref(task_queue_factory));
EXPECT_THAT(env.clock(), Ref(clock));
EXPECT_THAT(env.event_log(), Ref(event_log));
}
TEST(EnvironmentTest, UsesProvidedUtilitiesWithoutOwnership) {
FakeFieldTrials field_trials;
FakeTaskQueueFactory task_queue_factory;
SimulatedClock clock(Timestamp::Zero());
RtcEventLogNull event_log;
Environment env =
CreateEnvironment(&field_trials, &clock, &task_queue_factory, &event_log);
EXPECT_THAT(env.field_trials(), Ref(field_trials));
EXPECT_THAT(env.task_queue_factory(), Ref(task_queue_factory));
EXPECT_THAT(env.clock(), Ref(clock));
EXPECT_THAT(env.event_log(), Ref(event_log));
}
TEST(EnvironmentTest, UsesLastProvidedUtility) {
auto owned_field_trials1 = std::make_unique<FakeFieldTrials>();
auto owned_field_trials2 = std::make_unique<FakeFieldTrials>();
FieldTrialsView& field_trials2 = *owned_field_trials2;
Environment env = CreateEnvironment(std::move(owned_field_trials1),
std::move(owned_field_trials2));
EXPECT_THAT(env.field_trials(), Ref(field_trials2));
}
// Utilities can be provided from different sources, and when some source
// choose not to provide an utility, it is usually expressed with nullptr.
// When utility is not provided, it is natural to use previously set one.
// E.g. Both PeerConnectionFactoryDependencies and PeerConnectionDependencies
// provide field trials. When PeerConnectionDependencies::trials == nullptr,
// then trials from the PeerConnectionFactoryDependencies should be used.
// With nullptr accepted and ignored this can be expressed by
// `Environemt env = CreateEnvironment(pcf_deps.trials, pc_deps.trials);`
// That would use pc_deps.trials when not nullptr, pcf_deps.trials when
// pc_deps.trials is nullptr, but pcf_deps.trials is not, and default field
// trials when both are nullptr.
TEST(EnvironmentTest, IgnoresProvidedNullptrUtility) {
auto owned_field_trials = std::make_unique<FakeFieldTrials>();
std::unique_ptr<FieldTrialsView> null_field_trials = nullptr;
FieldTrialsView& field_trials = *owned_field_trials;
Environment env = CreateEnvironment(std::move(owned_field_trials),
std::move(null_field_trials));
EXPECT_THAT(env.field_trials(), Ref(field_trials));
}
TEST(EnvironmentTest, KeepsUtilityAliveWhileEnvironmentIsAlive) {
bool utility_destroyed = false;
auto field_trials = std::make_unique<FakeFieldTrials>(
/*on_destroyed=*/[&] { utility_destroyed = true; });
// Wrap Environment into optional to have explicit control when it is deleted.
absl::optional<Environment> env = CreateEnvironment(std::move(field_trials));
EXPECT_FALSE(utility_destroyed);
env = absl::nullopt;
EXPECT_TRUE(utility_destroyed);
}
TEST(EnvironmentTest, KeepsUtilityAliveWhileCopyOfEnvironmentIsAlive) {
bool utility_destroyed = false;
auto field_trials = std::make_unique<FakeFieldTrials>(
/*on_destroyed=*/[&] { utility_destroyed = true; });
absl::optional<Environment> env1 = CreateEnvironment(std::move(field_trials));
absl::optional<Environment> env2 = env1;
EXPECT_FALSE(utility_destroyed);
env1 = absl::nullopt;
EXPECT_FALSE(utility_destroyed);
env2 = absl::nullopt;
EXPECT_TRUE(utility_destroyed);
}
TEST(EnvironmentTest, FactoryCanBeReusedToCreateDifferentEnvironments) {
auto owned_task_queue_factory = std::make_unique<FakeTaskQueueFactory>();
auto owned_field_trials1 = std::make_unique<FakeFieldTrials>();
auto owned_field_trials2 = std::make_unique<FakeFieldTrials>();
TaskQueueFactory& task_queue_factory = *owned_task_queue_factory;
FieldTrialsView& field_trials1 = *owned_field_trials1;
FieldTrialsView& field_trials2 = *owned_field_trials2;
EnvironmentFactory factory;
factory.Set(std::move(owned_task_queue_factory));
factory.Set(std::move(owned_field_trials1));
Environment env1 = factory.Create();
factory.Set(std::move(owned_field_trials2));
Environment env2 = factory.Create();
// Environments share the same custom task queue factory.
EXPECT_THAT(env1.task_queue_factory(), Ref(task_queue_factory));
EXPECT_THAT(env2.task_queue_factory(), Ref(task_queue_factory));
// Environments have different field trials.
EXPECT_THAT(env1.field_trials(), Ref(field_trials1));
EXPECT_THAT(env2.field_trials(), Ref(field_trials2));
}
TEST(EnvironmentTest, FactoryCanCreateNewEnvironmentFromExistingOne) {
Environment env1 =
CreateEnvironment(std::make_unique<FakeTaskQueueFactory>());
EnvironmentFactory factory(env1);
factory.Set(std::make_unique<FakeFieldTrials>());
Environment env2 = factory.Create();
// Environments share the same default clock.
EXPECT_THAT(env2.clock(), Ref(env1.clock()));
// Environments share the same custom task queue factory.
EXPECT_THAT(env2.task_queue_factory(), Ref(env1.task_queue_factory()));
// Environments have different field trials.
EXPECT_THAT(env2.field_trials(), Not(Ref(env1.field_trials())));
}
TEST(EnvironmentTest, KeepsOwnershipsWhenCreateNewEnvironmentFromExistingOne) {
bool utility1_destroyed = false;
bool utility2_destroyed = false;
absl::optional<Environment> env1 =
CreateEnvironment(std::make_unique<FakeTaskQueueFactory>(
/*on_destroyed=*/[&] { utility1_destroyed = true; }));
absl::optional<EnvironmentFactory> factory = EnvironmentFactory(*env1);
// Destroy env1, check utility1 it was using is still alive.
env1 = absl::nullopt;
EXPECT_FALSE(utility1_destroyed);
factory->Set(std::make_unique<FakeFieldTrials>(
/*on_destroyed=*/[&] { utility2_destroyed = true; }));
absl::optional<Environment> env2 = factory->Create();
// Destroy the factory, check all utilities used by env2 are alive.
factory = absl::nullopt;
EXPECT_FALSE(utility1_destroyed);
EXPECT_FALSE(utility2_destroyed);
// Once last Environment object is deleted, utilties should be deleted too.
env2 = absl::nullopt;
EXPECT_TRUE(utility1_destroyed);
EXPECT_TRUE(utility2_destroyed);
}
TEST(EnvironmentTest, DestroysUtilitiesInReverseProvidedOrder) {
std::vector<std::string> destroyed;
auto field_trials = std::make_unique<FakeFieldTrials>(
/*on_destroyed=*/[&] { destroyed.push_back("field_trials"); });
auto task_queue_factory = std::make_unique<FakeTaskQueueFactory>(
/*on_destroyed=*/[&] { destroyed.push_back("task_queue_factory"); });
absl::optional<Environment> env =
CreateEnvironment(std::move(field_trials), std::move(task_queue_factory));
ASSERT_THAT(destroyed, IsEmpty());
env = absl::nullopt;
EXPECT_THAT(destroyed, ElementsAre("task_queue_factory", "field_trials"));
}
} // namespace
} // namespace webrtc