Add first L4S test using PeerScenario framework

The purpose is to be able to add more tests that verify that BWE still work and verify ECN behaviour e2e.

Bug: webrtc:42225697
Change-Id: Ie178d29d7870bfa3211d10925d00c621617ddf48
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/370561
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43511}
This commit is contained in:
Per Kjellander 2024-12-06 12:26:14 +00:00 committed by WebRTC LUCI CQ
parent 2ca8f15991
commit 67f9d7b4ed
2 changed files with 146 additions and 0 deletions

View File

@ -13,6 +13,7 @@ if (rtc_include_tests) {
testonly = true
sources = [
"bwe_ramp_up_test.cc",
"l4s_test.cc",
"peer_scenario_quality_test.cc",
"remote_estimate_test.cc",
"unsignaled_stream_test.cc",
@ -30,6 +31,7 @@ if (rtc_include_tests) {
"../../../pc:media_session",
"../../../pc:pc_test_utils",
"../../../pc:session_description",
"../../../rtc_base:logging",
]
if (rtc_enable_protobuf) {
deps += [

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2024 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 <atomic>
#include "api/units/time_delta.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet/congestion_control_feedback.h"
#include "modules/rtp_rtcp/source/rtcp_packet/rtpfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
#include "modules/rtp_rtcp/source/rtp_util.h"
#include "test/create_frame_generator_capturer.h"
#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/peer_scenario/peer_scenario.h"
#include "test/peer_scenario/peer_scenario_client.h"
namespace webrtc {
namespace {
using test::PeerScenario;
using test::PeerScenarioClient;
using ::testing::HasSubstr;
// Helper class used for counting RTCP feedback messages.
class RtcpFeedbackCounter {
public:
void Count(const EmulatedIpPacket& packet) {
if (!IsRtcpPacket(packet.data)) {
return;
}
rtcp::CommonHeader header;
ASSERT_TRUE(header.Parse(packet.data.cdata(), packet.data.size()));
if (header.type() != rtcp::Rtpfb::kPacketType) {
return;
}
if (header.fmt() == rtcp::CongestionControlFeedback::kFeedbackMessageType) {
++congestion_control_feedback_;
}
if (header.fmt() == rtcp::TransportFeedback::kFeedbackMessageType) {
++transport_sequence_number_feedback_;
}
}
int FeedbackAccordingToRfc8888() const {
return congestion_control_feedback_;
}
int FeedbackAccordingToTransportCc() const {
return transport_sequence_number_feedback_;
}
private:
int congestion_control_feedback_ = 0;
int transport_sequence_number_feedback_ = 0;
};
TEST(L4STest, NegotiateAndUseCcfbIfEnabled) {
test::ScopedFieldTrials trials(
"WebRTC-RFC8888CongestionControlFeedback/Enabled/");
PeerScenario s(*test_info_);
PeerScenarioClient::Config config = PeerScenarioClient::Config();
config.disable_encryption = true;
PeerScenarioClient* caller = s.CreateClient(config);
PeerScenarioClient* callee = s.CreateClient(config);
// Create network path from caller to callee.
auto send_node = s.net()->NodeBuilder().Build().node;
auto ret_node = s.net()->NodeBuilder().Build().node;
s.net()->CreateRoute(caller->endpoint(), {send_node}, callee->endpoint());
s.net()->CreateRoute(callee->endpoint(), {ret_node}, caller->endpoint());
RtcpFeedbackCounter send_node_feedback_counter;
send_node->router()->SetFilter([&](const EmulatedIpPacket& packet) {
send_node_feedback_counter.Count(packet);
return true;
});
RtcpFeedbackCounter ret_node_feedback_counter;
ret_node->router()->SetFilter([&](const EmulatedIpPacket& packet) {
ret_node_feedback_counter.Count(packet);
return true;
});
auto signaling = s.ConnectSignaling(caller, callee, {send_node}, {ret_node});
PeerScenarioClient::VideoSendTrackConfig video_conf;
video_conf.generator.squares_video->framerate = 15;
caller->CreateVideo("VIDEO_1", video_conf);
callee->CreateVideo("VIDEO_2", video_conf);
signaling.StartIceSignaling();
std::atomic<bool> offer_exchange_done(false);
signaling.NegotiateSdp(
[&](SessionDescriptionInterface* offer) {
std::string offer_str = absl::StrCat(*offer);
// Check that the offer contain both congestion control feedback
// accoring to RFC 8888, and transport-cc and the header extension
// http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
EXPECT_THAT(offer_str, HasSubstr("a=rtcp-fb:* ack ccfb\r\n"));
EXPECT_THAT(offer_str, HasSubstr("transport-cc"));
EXPECT_THAT(
offer_str,
HasSubstr("http://www.ietf.org/id/"
"draft-holmer-rmcat-transport-wide-cc-extensions"));
},
[&](const SessionDescriptionInterface& answer) {
std::string answer_str = absl::StrCat(answer);
EXPECT_THAT(answer_str, HasSubstr("a=rtcp-fb:* ack ccfb\r\n"));
// Check that the answer does not contain transport-cc nor the
// header extension
// http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
EXPECT_THAT(answer_str, Not(HasSubstr("transport-cc")));
EXPECT_THAT(
answer_str,
Not(HasSubstr(" http://www.ietf.org/id/"
"draft-holmer-rmcat-transport-wide-cc-extensions-")));
offer_exchange_done = true;
});
// Wait for SDP negotiation and the packet filter to be setup.
s.WaitAndProcess(&offer_exchange_done);
s.ProcessMessages(TimeDelta::Seconds(2));
EXPECT_GT(send_node_feedback_counter.FeedbackAccordingToRfc8888(), 0);
// TODO: bugs.webrtc.org/42225697 - Fix bug. Caller sends both transport
// sequence number feedback and congestion control feedback. So
// callee still send packets with transport sequence number header extensions
// even though it has been removed from the answer.
// EXPECT_EQ(send_node_feedback_counter.FeedbackAccordingToTransportCc(), 0);
EXPECT_GT(ret_node_feedback_counter.FeedbackAccordingToRfc8888(), 0);
EXPECT_EQ(ret_node_feedback_counter.FeedbackAccordingToTransportCc(), 0);
}
} // namespace
} // namespace webrtc