Implement delayed start of Scheduled network configuration

Before the schedule starts an absl::AnyInvocvable is executed every time
a packet is enqued. The incocable should return true, if the schedule should
be started.
The pupose is to allow tests to not start a schedule until ICE and DTLs
is connected.



Bug: webrtc:42224804
Change-Id: I61bd63508830f7c27d86f982299ce2be180ff460
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/354464
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42479}
This commit is contained in:
Per K 2024-06-13 06:49:17 +00:00 committed by WebRTC LUCI CQ
parent 2da85bc19a
commit da485a1b46
7 changed files with 87 additions and 7 deletions

View File

@ -26,6 +26,8 @@ if (rtc_enable_protobuf) {
":network_config_schedule_proto", ":network_config_schedule_proto",
"../..:network_emulation_manager_api", "../..:network_emulation_manager_api",
"../../../test/network:schedulable_network_behavior", "../../../test/network:schedulable_network_behavior",
"../../units:timestamp",
"//third_party/abseil-cpp/absl/functional:any_invocable",
] ]
} }
} }

View File

@ -12,8 +12,10 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "absl/functional/any_invocable.h"
#include "api/test/network_emulation/network_config_schedule.pb.h" #include "api/test/network_emulation/network_config_schedule.pb.h"
#include "api/test/network_emulation_manager.h" #include "api/test/network_emulation_manager.h"
#include "api/units/timestamp.h"
#include "test/network/schedulable_network_behavior.h" #include "test/network/schedulable_network_behavior.h"
namespace webrtc { namespace webrtc {
@ -21,10 +23,18 @@ namespace webrtc {
SchedulableNetworkNodeBuilder::SchedulableNetworkNodeBuilder( SchedulableNetworkNodeBuilder::SchedulableNetworkNodeBuilder(
webrtc::NetworkEmulationManager& net, webrtc::NetworkEmulationManager& net,
network_behaviour::NetworkConfigSchedule schedule) network_behaviour::NetworkConfigSchedule schedule)
: net_(net), schedule_(std::move(schedule)) {} : net_(net),
schedule_(std::move(schedule)),
start_condition_([](webrtc::Timestamp) { return true; }) {}
void SchedulableNetworkNodeBuilder::set_start_condition(
absl::AnyInvocable<bool(webrtc::Timestamp)> start_condition) {
start_condition_ = std::move(start_condition);
}
webrtc::EmulatedNetworkNode* SchedulableNetworkNodeBuilder::Build() { webrtc::EmulatedNetworkNode* SchedulableNetworkNodeBuilder::Build() {
return net_.CreateEmulatedNode(std::make_unique<SchedulableNetworkBehavior>( return net_.CreateEmulatedNode(std::make_unique<SchedulableNetworkBehavior>(
std::move(schedule_), *net_.time_controller()->GetClock())); std::move(schedule_), *net_.time_controller()->GetClock(),
std::move(start_condition_)));
} }
} // namespace webrtc } // namespace webrtc

View File

@ -10,8 +10,10 @@
#ifndef API_TEST_NETWORK_EMULATION_SCHEDULABLE_NETWORK_NODE_BUILDER_H_ #ifndef API_TEST_NETWORK_EMULATION_SCHEDULABLE_NETWORK_NODE_BUILDER_H_
#define API_TEST_NETWORK_EMULATION_SCHEDULABLE_NETWORK_NODE_BUILDER_H_ #define API_TEST_NETWORK_EMULATION_SCHEDULABLE_NETWORK_NODE_BUILDER_H_
#include "absl/functional/any_invocable.h"
#include "api/test/network_emulation/network_config_schedule.pb.h" #include "api/test/network_emulation/network_config_schedule.pb.h"
#include "api/test/network_emulation_manager.h" #include "api/test/network_emulation_manager.h"
#include "api/units/timestamp.h"
namespace webrtc { namespace webrtc {
@ -20,12 +22,20 @@ class SchedulableNetworkNodeBuilder {
SchedulableNetworkNodeBuilder( SchedulableNetworkNodeBuilder(
webrtc::NetworkEmulationManager& net, webrtc::NetworkEmulationManager& net,
network_behaviour::NetworkConfigSchedule schedule); network_behaviour::NetworkConfigSchedule schedule);
// set_start_condition allows a test to control when the schedule start.
// `start_condition` is invoked every time a packet is enqueued on the network
// until the first time `start_condition` returns true. Until then, the first
// NetworkConfigScheduleItem is used. There is no guarantee on which
// thread/task queue that will be used.
void set_start_condition(
absl::AnyInvocable<bool(webrtc::Timestamp)> start_condition);
webrtc::EmulatedNetworkNode* Build(); webrtc::EmulatedNetworkNode* Build();
private: private:
webrtc::NetworkEmulationManager& net_; webrtc::NetworkEmulationManager& net_;
network_behaviour::NetworkConfigSchedule schedule_; network_behaviour::NetworkConfigSchedule schedule_;
absl::AnyInvocable<bool(webrtc::Timestamp)> start_condition_;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -265,6 +265,7 @@ if (rtc_enable_protobuf) {
"../../rtc_base:macromagic", "../../rtc_base:macromagic",
"../../rtc_base/task_utils:repeating_task", "../../rtc_base/task_utils:repeating_task",
"../../system_wrappers", "../../system_wrappers",
"//third_party/abseil-cpp/absl/functional:any_invocable",
] ]
} }

View File

@ -11,8 +11,8 @@
#include <utility> #include <utility>
#include "absl/functional/any_invocable.h"
#include "api/sequence_checker.h" #include "api/sequence_checker.h"
#include "api/task_queue/task_queue_base.h"
#include "api/test/network_emulation/network_config_schedule.pb.h" #include "api/test/network_emulation/network_config_schedule.pb.h"
#include "api/test/simulated_network.h" #include "api/test/simulated_network.h"
#include "api/units/data_rate.h" #include "api/units/data_rate.h"
@ -72,9 +72,11 @@ BuiltInNetworkBehaviorConfig GetInitialConfig(
SchedulableNetworkBehavior::SchedulableNetworkBehavior( SchedulableNetworkBehavior::SchedulableNetworkBehavior(
network_behaviour::NetworkConfigSchedule schedule, network_behaviour::NetworkConfigSchedule schedule,
webrtc::Clock& clock) webrtc::Clock& clock,
absl::AnyInvocable<bool(webrtc::Timestamp)> start_callback)
: SimulatedNetwork(GetInitialConfig(schedule)), : SimulatedNetwork(GetInitialConfig(schedule)),
schedule_(std::move(schedule)), schedule_(std::move(schedule)),
start_condition_(std::move(start_callback)),
clock_(clock), clock_(clock),
config_(GetInitialConfig(schedule_)) { config_(GetInitialConfig(schedule_)) {
if (schedule_.item().size() > 1) { if (schedule_.item().size() > 1) {
@ -86,7 +88,8 @@ SchedulableNetworkBehavior::SchedulableNetworkBehavior(
bool SchedulableNetworkBehavior::EnqueuePacket( bool SchedulableNetworkBehavior::EnqueuePacket(
webrtc::PacketInFlightInfo packet_info) { webrtc::PacketInFlightInfo packet_info) {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
if (first_send_time_.IsMinusInfinity()) { if (first_send_time_.IsInfinite() &&
start_condition_(webrtc::Timestamp::Micros(packet_info.send_time_us))) {
first_send_time_ = webrtc::Timestamp::Micros(packet_info.send_time_us); first_send_time_ = webrtc::Timestamp::Micros(packet_info.send_time_us);
if (schedule_.item().size() > 1) { if (schedule_.item().size() > 1) {
RTC_CHECK_LT(next_schedule_index_, schedule_.item().size()); RTC_CHECK_LT(next_schedule_index_, schedule_.item().size());

View File

@ -11,6 +11,7 @@
#ifndef TEST_NETWORK_SCHEDULABLE_NETWORK_BEHAVIOR_H_ #ifndef TEST_NETWORK_SCHEDULABLE_NETWORK_BEHAVIOR_H_
#define TEST_NETWORK_SCHEDULABLE_NETWORK_BEHAVIOR_H_ #define TEST_NETWORK_SCHEDULABLE_NETWORK_BEHAVIOR_H_
#include "absl/functional/any_invocable.h"
#include "api/sequence_checker.h" #include "api/sequence_checker.h"
#include "api/test/network_emulation/network_config_schedule.pb.h" #include "api/test/network_emulation/network_config_schedule.pb.h"
#include "api/test/simulated_network.h" #include "api/test/simulated_network.h"
@ -27,8 +28,11 @@ namespace webrtc {
// specified with a schedule proto. // specified with a schedule proto.
class SchedulableNetworkBehavior : public SimulatedNetwork { class SchedulableNetworkBehavior : public SimulatedNetwork {
public: public:
SchedulableNetworkBehavior(network_behaviour::NetworkConfigSchedule schedule, SchedulableNetworkBehavior(
Clock& clock); network_behaviour::NetworkConfigSchedule schedule,
Clock& clock,
absl::AnyInvocable<bool(webrtc::Timestamp)> start_condition =
[](webrtc::Timestamp) { return true; });
bool EnqueuePacket(PacketInFlightInfo packet_info) override; bool EnqueuePacket(PacketInFlightInfo packet_info) override;
@ -37,6 +41,10 @@ class SchedulableNetworkBehavior : public SimulatedNetwork {
SequenceChecker sequence_checker_; SequenceChecker sequence_checker_;
const network_behaviour::NetworkConfigSchedule schedule_; const network_behaviour::NetworkConfigSchedule schedule_;
absl::AnyInvocable<bool(webrtc::Timestamp)> start_condition_
RTC_GUARDED_BY(&sequence_checker_);
// Send time of the first packet enqueued after `start_condition_` return
// true.
Timestamp first_send_time_ RTC_GUARDED_BY(&sequence_checker_) = Timestamp first_send_time_ RTC_GUARDED_BY(&sequence_checker_) =
Timestamp::MinusInfinity(); Timestamp::MinusInfinity();

View File

@ -27,6 +27,8 @@ namespace {
using ::testing::Mock; using ::testing::Mock;
using ::testing::MockFunction; using ::testing::MockFunction;
using ::testing::Return;
using ::testing::Sequence;
using ::testing::SizeIs; using ::testing::SizeIs;
class SchedulableNetworkBehaviorTestFixture { class SchedulableNetworkBehaviorTestFixture {
@ -147,6 +149,50 @@ TEST(SchedulableNetworkBehaviorTest,
.us()); .us());
} }
TEST(SchedulableNetworkBehaviorTest, ScheduleStartedWhenStartConditionTrue) {
SchedulableNetworkBehaviorTestFixture fixture;
network_behaviour::NetworkConfigSchedule schedule;
auto initial_config = schedule.add_item();
initial_config->set_link_capacity_kbps(0);
auto item = schedule.add_item();
item->set_time_since_first_sent_packet_ms(1);
item->set_link_capacity_kbps(1000000);
MockFunction<bool(Timestamp)> start_condition;
webrtc::Timestamp first_packet_send_time = fixture.TimeNow();
webrtc::Timestamp second_packet_send_time =
fixture.TimeNow() + TimeDelta::Millis(100);
Sequence s;
EXPECT_CALL(start_condition, Call(first_packet_send_time))
.InSequence(s)
.WillOnce(Return(false));
// Expect schedule to start when the second packet is sent.
EXPECT_CALL(start_condition, Call(second_packet_send_time))
.InSequence(s)
.WillOnce(Return(true));
SchedulableNetworkBehavior network_behaviour(schedule, fixture.clock(),
start_condition.AsStdFunction());
EXPECT_TRUE(network_behaviour.EnqueuePacket(
{/*size=*/1000 / 8,
/*send_time_us=*/first_packet_send_time.us(),
/*packet_id=*/1}));
EXPECT_FALSE(network_behaviour.NextDeliveryTimeUs().has_value());
// Move passed the normal schedule change time. Still dont expect a delivery
// time.
fixture.AdvanceTime(TimeDelta::Millis(100));
EXPECT_FALSE(network_behaviour.NextDeliveryTimeUs().has_value());
EXPECT_TRUE(network_behaviour.EnqueuePacket(
{/*size=*/1000 / 8,
/*send_time_us=*/second_packet_send_time.us(),
/*packet_id=*/2}));
EXPECT_FALSE(network_behaviour.NextDeliveryTimeUs().has_value());
fixture.AdvanceTime(TimeDelta::Millis(1));
EXPECT_TRUE(network_behaviour.NextDeliveryTimeUs().has_value());
}
TEST(SchedulableNetworkBehaviorTest, ScheduleWithRepeat) { TEST(SchedulableNetworkBehaviorTest, ScheduleWithRepeat) {
SchedulableNetworkBehaviorTestFixture fixture; SchedulableNetworkBehaviorTestFixture fixture;
network_behaviour::NetworkConfigSchedule schedule; network_behaviour::NetworkConfigSchedule schedule;