Introduce CreateTestEnvironment and update test/ to use it

The helper proposed as primary way to construct Environment in tests
Unlike prod CreateEnvironment it use command line base field trials by default.
It also aware of test-only TimeController interface and make it simpler to use it.

Bug: None
Change-Id: If207a374a0dccc4f3f4064f0cbfccc63c4dc8f6f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/403760
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Jeremy Leconte <jleconte@google.com>
Cr-Commit-Position: refs/heads/main@{#45324}
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 4a6e127..2e8752a 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -149,6 +149,25 @@
   ]
 }
 
+rtc_library("create_test_environment") {
+  testonly = true
+  sources = [
+    "create_test_environment.cc",
+    "create_test_environment.h",
+  ]
+  deps = [
+    ":create_test_field_trials",
+    "../api:field_trials",
+    "../api:field_trials_view",
+    "../api:time_controller",
+    "../api/environment",
+    "../api/environment:environment_factory",
+    "../rtc_base:checks",
+    "//third_party/abseil-cpp/absl/base:nullability",
+    "//third_party/abseil-cpp/absl/strings:string_view",
+  ]
+}
+
 rtc_library("create_test_field_trials") {
   testonly = true
   sources = [ "create_test_field_trials.h" ]
@@ -682,6 +701,7 @@
         ":call_config_utils",
         ":copy_to_file_audio_capturer_unittest",
         ":create_frame_generator_capturer",
+        ":create_test_environment",
         ":create_test_field_trials",
         ":direct_transport",
         ":fake_video_codecs",
@@ -1261,6 +1281,7 @@
     ]
 
     deps = [
+      ":create_test_environment",
       ":create_test_field_trials",
       ":direct_transport",
       ":encoder_settings",
@@ -1433,7 +1454,6 @@
     "../api:make_ref_counted",
     "../api:scoped_refptr",
     "../api/environment",
-    "../api/environment:environment_factory",
     "../api/numerics",
     "../api/test/metrics:metric",
     "../api/test/metrics:metrics_logger",
diff --git a/test/call_test.cc b/test/call_test.cc
index 0117542..6d42d5f 100644
--- a/test/call_test.cc
+++ b/test/call_test.cc
@@ -58,6 +58,7 @@
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/task_queue_for_test.h"
+#include "test/create_test_environment.h"
 #include "test/create_test_field_trials.h"
 #include "test/encoder_settings.h"
 #include "test/fake_decoder.h"
@@ -75,7 +76,7 @@
 
 CallTest::CallTest(absl::string_view field_trials)
     : field_trials_(CreateTestFieldTrials(field_trials)),
-      env_(CreateEnvironment(&field_trials_)),
+      env_(CreateTestEnvironment({.field_trials = &field_trials_})),
       send_env_(env_),
       recv_env_(env_),
       audio_send_config_(/*send_transport=*/nullptr),
diff --git a/test/create_test_environment.cc b/test/create_test_environment.cc
new file mode 100644
index 0000000..2be05ae
--- /dev/null
+++ b/test/create_test_environment.cc
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2025 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 "test/create_test_environment.h"
+
+#include <memory>
+#include <utility>
+#include <variant>
+
+#include "absl/base/nullability.h"
+#include "absl/strings/string_view.h"
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
+#include "api/field_trials.h"
+#include "api/field_trials_view.h"
+#include "rtc_base/checks.h"
+#include "test/create_test_field_trials.h"
+
+namespace webrtc {
+namespace {
+
+struct SetFieldTrials {
+  void operator()(absl::string_view field_trials) {
+    factory.Set(CreateTestFieldTrialsPtr(field_trials));
+  }
+
+  void operator()(FieldTrialsView* absl_nonnull field_trials) {
+    RTC_CHECK(field_trials != nullptr);
+    factory.Set(field_trials);
+  }
+
+  void operator()(absl_nonnull std::unique_ptr<FieldTrialsView> field_trials) {
+    RTC_CHECK(field_trials != nullptr);
+    factory.Set(std::move(field_trials));
+  }
+
+  void operator()(FieldTrials field_trials) {
+    factory.Set(std::make_unique<FieldTrials>(std::move(field_trials)));
+  }
+
+  EnvironmentFactory& factory;
+};
+
+}  // namespace
+
+Environment CreateTestEnvironment(CreateTestEnvironmentOptions o) {
+  EnvironmentFactory factory;
+
+  std::visit(SetFieldTrials{factory}, std::move(o.field_trials));
+
+  if (o.time != nullptr) {
+    factory.Set(o.time->GetClock());
+    factory.Set(o.time->GetTaskQueueFactory());
+  }
+  return factory.Create();
+}
+
+}  // namespace webrtc
diff --git a/test/create_test_environment.h b/test/create_test_environment.h
new file mode 100644
index 0000000..606c081
--- /dev/null
+++ b/test/create_test_environment.h
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2025 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 TEST_CREATE_TEST_ENVIRONMENT_H_
+#define TEST_CREATE_TEST_ENVIRONMENT_H_
+
+#include <memory>
+#include <variant>
+
+#include "absl/base/nullability.h"
+#include "absl/strings/string_view.h"
+#include "api/environment/environment.h"
+#include "api/field_trials.h"
+#include "api/field_trials_view.h"
+#include "api/test/time_controller.h"
+
+namespace webrtc {
+
+// Creates Environment for unittests. Uses test specific defaults unlike the
+// production CreateEnvironment.
+// Supports test only interface TimeController for testing with simulated time.
+// TODO: bugs.webrtc.org/437878267 - Remove `FieldTrialsView*` variant when
+// tests are refactored not to rely on it.
+struct CreateTestEnvironmentOptions {
+  std::variant<absl::string_view,
+               FieldTrialsView * absl_nonnull,
+               absl_nonnull std::unique_ptr<FieldTrialsView>,
+               FieldTrials>
+      field_trials;
+  TimeController* time = nullptr;
+};
+Environment CreateTestEnvironment(CreateTestEnvironmentOptions o = {});
+
+}  // namespace webrtc
+
+#endif  // TEST_CREATE_TEST_ENVIRONMENT_H_
diff --git a/test/network/BUILD.gn b/test/network/BUILD.gn
index a9dcdd7..f26dfb6 100644
--- a/test/network/BUILD.gn
+++ b/test/network/BUILD.gn
@@ -102,6 +102,7 @@
     deps = [
       ":emulated_network",
       ":simulated_network",
+      "..:create_test_environment",
       "..:test_support",
       "..:wait_until",
       "../../api:audio_options_api",
diff --git a/test/network/network_emulation_pc_unittest.cc b/test/network/network_emulation_pc_unittest.cc
index 8310f3d..7ddc525 100644
--- a/test/network/network_emulation_pc_unittest.cc
+++ b/test/network/network_emulation_pc_unittest.cc
@@ -16,7 +16,6 @@
 #include "api/create_modular_peer_connection_factory.h"
 #include "api/enable_media_with_defaults.h"
 #include "api/environment/environment.h"
-#include "api/environment/environment_factory.h"
 #include "api/jsep.h"
 #include "api/media_stream_interface.h"
 #include "api/peer_connection_interface.h"
@@ -32,6 +31,7 @@
 #include "pc/test/mock_peer_connection_observers.h"
 #include "rtc_base/task_queue_for_test.h"
 #include "rtc_base/thread.h"
+#include "test/create_test_environment.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/network/network_emulation.h"
@@ -64,7 +64,7 @@
 scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
     Thread* signaling_thread,
     EmulatedNetworkManagerInterface* network) {
-  const Environment env = CreateEnvironment();
+  const Environment env = CreateTestEnvironment();
   PeerConnectionFactoryDependencies pcf_deps;
   pcf_deps.env = env;
   pcf_deps.event_log_factory = std::make_unique<RtcEventLogFactory>();
diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn
index 3a32fd0..ee466a0 100644
--- a/test/pc/e2e/BUILD.gn
+++ b/test/pc/e2e/BUILD.gn
@@ -106,6 +106,7 @@
         ":echo_emulation",
         ":test_peer",
         "../..:copy_to_file_audio_capturer",
+        "../..:create_test_environment",
         "../../../api:create_modular_peer_connection_factory",
         "../../../api:enable_media_with_defaults",
         "../../../api:libjingle_peerconnection_api",
diff --git a/test/pc/e2e/test_peer_factory.cc b/test/pc/e2e/test_peer_factory.cc
index 981e38d..5c089b7 100644
--- a/test/pc/e2e/test_peer_factory.cc
+++ b/test/pc/e2e/test_peer_factory.cc
@@ -22,7 +22,6 @@
 #include "api/create_modular_peer_connection_factory.h"
 #include "api/enable_media_with_defaults.h"
 #include "api/environment/environment.h"
-#include "api/environment/environment_factory.h"
 #include "api/peer_connection_interface.h"
 #include "api/rtc_event_log/rtc_event_log_factory.h"
 #include "api/scoped_refptr.h"
@@ -39,6 +38,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/system/file_wrapper.h"
 #include "rtc_base/thread.h"
+#include "test/create_test_environment.h"
 #include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h"
 #include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h"
 #include "test/pc/e2e/echo/echo_emulation.h"
@@ -292,9 +292,9 @@
   SetMandatoryEntities(components.get());
   params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
 
-  const Environment env = CreateEnvironment(
-      std::move(components->pcf_dependencies->field_trials),
-      time_controller_.GetClock(), time_controller_.GetTaskQueueFactory());
+  const Environment env = CreateTestEnvironment(
+      {.field_trials = std::move(components->pcf_dependencies->field_trials),
+       .time = &time_controller_});
 
   // Create peer connection factory.
   scoped_refptr<AudioDeviceModule> audio_device_module =
diff --git a/test/peer_scenario/BUILD.gn b/test/peer_scenario/BUILD.gn
index d644ea3..456fa43 100644
--- a/test/peer_scenario/BUILD.gn
+++ b/test/peer_scenario/BUILD.gn
@@ -23,6 +23,7 @@
     ]
     deps = [
       "..:create_frame_generator_capturer",
+      "..:create_test_environment",
       "..:create_test_field_trials",
       "..:fake_video_codecs",
       "..:fileutils",
diff --git a/test/peer_scenario/peer_scenario_client.cc b/test/peer_scenario/peer_scenario_client.cc
index 6fb8989..e9aa2ae 100644
--- a/test/peer_scenario/peer_scenario_client.cc
+++ b/test/peer_scenario/peer_scenario_client.cc
@@ -26,8 +26,6 @@
 #include "api/data_channel_interface.h"
 #include "api/enable_media_with_defaults.h"
 #include "api/environment/environment.h"
-#include "api/environment/environment_factory.h"
-#include "api/field_trials.h"
 #include "api/jsep.h"
 #include "api/make_ref_counted.h"
 #include "api/media_stream_interface.h"
@@ -69,6 +67,7 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/thread.h"
 #include "test/create_frame_generator_capturer.h"
+#include "test/create_test_environment.h"
 #include "test/fake_decoder.h"
 #include "test/fake_vp8_encoder.h"
 #include "test/frame_generator_capturer.h"
@@ -242,10 +241,9 @@
     Thread* signaling_thread,
     std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,
     PeerScenarioClient::Config config)
-    : env_(CreateEnvironment(
-          std::make_unique<FieldTrials>(std::move(config.field_trials)),
-          net->time_controller()->GetClock(),
-          net->time_controller()->GetTaskQueueFactory())),
+    : env_(
+          CreateTestEnvironment({.field_trials = std::move(config.field_trials),
+                                 .time = net->time_controller()})),
       endpoints_(CreateEndpoints(net, config.endpoints)),
       signaling_thread_(signaling_thread),
       log_writer_factory_(std::move(log_writer_factory)),
diff --git a/test/scenario/BUILD.gn b/test/scenario/BUILD.gn
index 4b6f8f5..76a6455 100644
--- a/test/scenario/BUILD.gn
+++ b/test/scenario/BUILD.gn
@@ -71,6 +71,7 @@
     ]
     deps = [
       ":column_printer",
+      "..:create_test_environment",
       "..:create_test_field_trials",
       "..:encoder_settings",
       "..:frame_generator_capturer",
diff --git a/test/scenario/call_client.cc b/test/scenario/call_client.cc
index 0b88502..56a6c1b 100644
--- a/test/scenario/call_client.cc
+++ b/test/scenario/call_client.cc
@@ -20,7 +20,6 @@
 #include "api/audio/builtin_audio_processing_builder.h"
 #include "api/environment/environment.h"
 #include "api/environment/environment_factory.h"
-#include "api/field_trials.h"
 #include "api/media_types.h"
 #include "api/rtc_event_log/rtc_event_log.h"
 #include "api/rtc_event_log/rtc_event_log_factory.h"
@@ -48,6 +47,7 @@
 #include "rtc_base/event.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/string_builder.h"
+#include "test/create_test_environment.h"
 #include "test/logging/log_writer.h"
 #include "test/scenario/column_printer.h"
 #include "test/scenario/network_node.h"
@@ -235,10 +235,9 @@
     std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,
     CallClientConfig config)
     : time_controller_(time_controller),
-      env_(CreateEnvironment(
-          std::make_unique<FieldTrials>(std::move(config.field_trials)),
-          time_controller_->CreateTaskQueueFactory(),
-          time_controller_->GetClock())),
+      env_(
+          CreateTestEnvironment({.field_trials = std::move(config.field_trials),
+                                 .time = time_controller_})),
       log_writer_factory_(std::move(log_writer_factory)),
       network_controller_factory_(log_writer_factory_.get(), config.transport),
       task_queue_(env_.task_queue_factory().CreateTaskQueue(
diff --git a/test/testsupport/ivf_video_frame_generator_unittest.cc b/test/testsupport/ivf_video_frame_generator_unittest.cc
index fb5ede5..eb9b940 100644
--- a/test/testsupport/ivf_video_frame_generator_unittest.cc
+++ b/test/testsupport/ivf_video_frame_generator_unittest.cc
@@ -18,7 +18,6 @@
 #include <vector>
 
 #include "api/environment/environment.h"
-#include "api/environment/environment_factory.h"
 #include "api/scoped_refptr.h"
 #include "api/test/create_frame_generator.h"
 #include "api/test/frame_generator_interface.h"
@@ -40,6 +39,7 @@
 #include "rtc_base/event.h"
 #include "rtc_base/system/file_wrapper.h"
 #include "rtc_base/thread_annotations.h"
+#include "test/create_test_environment.h"
 #include "test/gtest.h"
 #include "test/testsupport/file_utils.h"
 #include "test/video_codec_settings.h"
@@ -170,7 +170,7 @@
         kMaxFrameEncodeWaitTimeout));
   }
 
-  Environment env_ = CreateEnvironment();
+  Environment env_ = CreateTestEnvironment();
   std::string file_name_;
   std::vector<VideoFrame> video_frames_;
 };
diff --git a/test/video_codec_tester.cc b/test/video_codec_tester.cc
index 8d647c9..7df9dbd 100644
--- a/test/video_codec_tester.cc
+++ b/test/video_codec_tester.cc
@@ -33,7 +33,6 @@
 #include "absl/strings/string_view.h"
 #include "api/array_view.h"
 #include "api/environment/environment.h"
-#include "api/environment/environment_factory.h"
 #include "api/field_trials_view.h"
 #include "api/make_ref_counted.h"
 #include "api/numerics/samples_stats_counter.h"
@@ -137,11 +136,11 @@
 // AV1 or H264) files.
 class VideoSource {
  public:
-  explicit VideoSource(VideoSourceSettings source_settings)
+  VideoSource(const Environment& env, VideoSourceSettings source_settings)
       : source_settings_(source_settings) {
     if (absl::EndsWith(source_settings.file_path, "ivf")) {
-      ivf_reader_ = CreateFromIvfFileFrameGenerator(CreateEnvironment(),
-                                                    source_settings.file_path);
+      ivf_reader_ =
+          CreateFromIvfFileFrameGenerator(env, source_settings.file_path);
     } else if (absl::EndsWith(source_settings.file_path, "y4m")) {
       yuv_reader_ =
           CreateY4mFrameReader(source_settings_.file_path,
@@ -1692,7 +1691,7 @@
     VideoEncoderFactory* encoder_factory,
     const EncoderSettings& encoder_settings,
     const std::map<uint32_t, EncodingSettings>& encoding_settings) {
-  VideoSource video_source(source_settings);
+  VideoSource video_source(env, source_settings);
   std::unique_ptr<VideoCodecAnalyzer> analyzer =
       std::make_unique<VideoCodecAnalyzer>();
   Encoder encoder(env, encoder_factory, encoder_settings, analyzer.get());
@@ -1721,7 +1720,7 @@
     const EncoderSettings& encoder_settings,
     const DecoderSettings& decoder_settings,
     const std::map<uint32_t, EncodingSettings>& encoding_settings) {
-  VideoSource video_source(source_settings);
+  VideoSource video_source(env, source_settings);
   std::unique_ptr<VideoCodecAnalyzer> analyzer =
       std::make_unique<VideoCodecAnalyzer>();
   const EncodingSettings& first_frame_settings =
diff --git a/test/video_codec_tester_unittest.cc b/test/video_codec_tester_unittest.cc
index 86fea7c..69e7d50 100644
--- a/test/video_codec_tester_unittest.cc
+++ b/test/video_codec_tester_unittest.cc
@@ -25,7 +25,6 @@
 #include <vector>
 
 #include "api/environment/environment.h"
-#include "api/environment/environment_factory.h"
 #include "api/scoped_refptr.h"
 #include "api/test/mock_video_decoder.h"
 #include "api/test/mock_video_decoder_factory.h"
@@ -50,6 +49,7 @@
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "modules/video_coding/include/video_error_codes.h"
 #include "modules/video_coding/svc/scalability_mode_util.h"
+#include "test/create_test_environment.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/testsupport/file_utils.h"
@@ -277,7 +277,7 @@
   }
 
  protected:
-  const Environment env_ = CreateEnvironment();
+  const Environment env_ = CreateTestEnvironment();
   std::vector<std::unique_ptr<TestVideoDecoder>> decoders_;
 };
 
@@ -649,13 +649,13 @@
   void TearDown() override { remove(source_yuv_file_path_.c_str()); }
 
  protected:
-  const Environment env_ = CreateEnvironment();
+  const Environment env_ = CreateTestEnvironment();
   std::string source_yuv_file_path_;
 };
 
 TEST_P(VideoCodecTesterTestPacing, PaceEncode) {
   auto [pacing_settings, expected_delta_ms] = GetParam();
-  const Environment env = CreateEnvironment();
+  const Environment env = CreateTestEnvironment();
   VideoSourceSettings video_source{
       .file_path = source_yuv_file_path_,
       .resolution = {.width = kSourceWidth, .height = kSourceHeight},
@@ -734,7 +734,8 @@
 TEST_P(VideoCodecTesterTestEncodingSettings, CreateEncodingSettings) {
   EncodingSettingsTestParameters test_params = GetParam();
   EncodingSettings encoding_settings = VideoCodecTester::CreateEncodingSettings(
-      CreateEnvironment(), test_params.codec_type, test_params.scalability_mode,
+      CreateTestEnvironment(), test_params.codec_type,
+      test_params.scalability_mode,
       /*width=*/1280,
       /*height=*/720, test_params.bitrate, kFramerate);
   const std::map<LayerId, LayerSettings>& layers_settings =
@@ -920,7 +921,7 @@
 
 // TODO(webrtc:42225151): Add an IVF test stream and enable the test.
 TEST(VideoCodecTester, DISABLED_CompressedVideoSource) {
-  const Environment env = CreateEnvironment();
+  const Environment env = CreateTestEnvironment();
   std::unique_ptr<VideoEncoderFactory> encoder_factory =
       CreateBuiltinVideoEncoderFactory();
   std::unique_ptr<VideoDecoderFactory> decoder_factory =