Add pure RtpSenderEgress unit test fixture.
The extracts and refactors some test code from rtp_sender_unittest.cc and puts it in a new target intended to only test RtpSenderEgress, and do it as pure unit test, rather than the unholy not-quite-unit-not-quite-integration-test thingy we have today. Only a first test case is actually ported with this CL, but it's a start... Bug: webrtc:11340 Change-Id: Ie2cdde63a00a6ff6eba7b8d443eeb76ce2a527c9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/216180 Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Commit-Queue: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33841}
This commit is contained in:
@ -531,6 +531,7 @@ if (rtc_include_tests) {
|
||||
"source/rtp_rtcp_impl2_unittest.cc",
|
||||
"source/rtp_rtcp_impl_unittest.cc",
|
||||
"source/rtp_sender_audio_unittest.cc",
|
||||
"source/rtp_sender_egress_unittest.cc",
|
||||
"source/rtp_sender_unittest.cc",
|
||||
"source/rtp_sender_video_unittest.cc",
|
||||
"source/rtp_sequence_number_map_unittest.cc",
|
||||
@ -566,6 +567,7 @@ if (rtc_include_tests) {
|
||||
"../../api/rtc_event_log",
|
||||
"../../api/transport:field_trial_based_config",
|
||||
"../../api/transport/rtp:dependency_descriptor",
|
||||
"../../api/units:data_size",
|
||||
"../../api/units:timestamp",
|
||||
"../../api/video:encoded_image",
|
||||
"../../api/video:video_bitrate_allocation",
|
||||
|
||||
228
modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc
Normal file
228
modules/rtp_rtcp/source/rtp_sender_egress_unittest.cc
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "modules/rtp_rtcp/source/rtp_sender_egress.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/call/transport.h"
|
||||
#include "api/units/data_size.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_history.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/time_controller/simulated_time_controller.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using ::testing::Field;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
constexpr Timestamp kStartTime = Timestamp::Millis(123456789);
|
||||
constexpr int kDefaultPayloadType = 100;
|
||||
constexpr uint16_t kStartSequenceNumber = 33;
|
||||
constexpr uint32_t kSsrc = 725242;
|
||||
constexpr uint32_t kRtxSsrc = 12345;
|
||||
enum : int {
|
||||
kTransportSequenceNumberExtensionId = 1,
|
||||
};
|
||||
|
||||
struct TestConfig {
|
||||
explicit TestConfig(bool with_overhead) : with_overhead(with_overhead) {}
|
||||
bool with_overhead = false;
|
||||
};
|
||||
|
||||
class MockSendPacketObserver : public SendPacketObserver {
|
||||
public:
|
||||
MOCK_METHOD(void, OnSendPacket, (uint16_t, int64_t, uint32_t), (override));
|
||||
};
|
||||
|
||||
class MockTransportFeedbackObserver : public TransportFeedbackObserver {
|
||||
public:
|
||||
MOCK_METHOD(void, OnAddPacket, (const RtpPacketSendInfo&), (override));
|
||||
MOCK_METHOD(void,
|
||||
OnTransportFeedback,
|
||||
(const rtcp::TransportFeedback&),
|
||||
(override));
|
||||
};
|
||||
|
||||
class MockStreamDataCountersCallback : public StreamDataCountersCallback {
|
||||
public:
|
||||
MOCK_METHOD(void,
|
||||
DataCountersUpdated,
|
||||
(const StreamDataCounters& counters, uint32_t ssrc),
|
||||
(override));
|
||||
};
|
||||
|
||||
class FieldTrialConfig : public WebRtcKeyValueConfig {
|
||||
public:
|
||||
FieldTrialConfig() : overhead_enabled_(false) {}
|
||||
~FieldTrialConfig() override {}
|
||||
|
||||
void SetOverHeadEnabled(bool enabled) { overhead_enabled_ = enabled; }
|
||||
|
||||
std::string Lookup(absl::string_view key) const override {
|
||||
if (key == "WebRTC-SendSideBwe-WithOverhead") {
|
||||
return overhead_enabled_ ? "Enabled" : "Disabled";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
bool overhead_enabled_;
|
||||
};
|
||||
|
||||
struct TransmittedPacket {
|
||||
TransmittedPacket(rtc::ArrayView<const uint8_t> data,
|
||||
const PacketOptions& packet_options,
|
||||
RtpHeaderExtensionMap* extensions)
|
||||
: packet(extensions), options(packet_options) {
|
||||
EXPECT_TRUE(packet.Parse(data));
|
||||
}
|
||||
RtpPacketReceived packet;
|
||||
PacketOptions options;
|
||||
};
|
||||
|
||||
class TestTransport : public Transport {
|
||||
public:
|
||||
explicit TestTransport(RtpHeaderExtensionMap* extensions)
|
||||
: total_data_sent_(DataSize::Zero()), extensions_(extensions) {}
|
||||
bool SendRtp(const uint8_t* packet,
|
||||
size_t length,
|
||||
const PacketOptions& options) override {
|
||||
total_data_sent_ += DataSize::Bytes(length);
|
||||
last_packet_.emplace(rtc::MakeArrayView(packet, length), options,
|
||||
extensions_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SendRtcp(const uint8_t*, size_t) override { RTC_CHECK_NOTREACHED(); }
|
||||
|
||||
absl::optional<TransmittedPacket> last_packet() { return last_packet_; }
|
||||
|
||||
private:
|
||||
DataSize total_data_sent_;
|
||||
absl::optional<TransmittedPacket> last_packet_;
|
||||
RtpHeaderExtensionMap* const extensions_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class RtpSenderEgressTest : public ::testing::TestWithParam<TestConfig> {
|
||||
protected:
|
||||
RtpSenderEgressTest()
|
||||
: time_controller_(kStartTime),
|
||||
clock_(time_controller_.GetClock()),
|
||||
transport_(&header_extensions_),
|
||||
packet_history_(clock_, /*enable_rtx_padding_prioritization=*/true),
|
||||
sequence_number_(kStartSequenceNumber) {
|
||||
trials_.SetOverHeadEnabled(GetParam().with_overhead);
|
||||
}
|
||||
|
||||
std::unique_ptr<RtpSenderEgress> CreateRtpSenderEgress() {
|
||||
return std::make_unique<RtpSenderEgress>(DefaultConfig(), &packet_history_);
|
||||
}
|
||||
|
||||
RtpRtcp::Configuration DefaultConfig() {
|
||||
RtpRtcp::Configuration config;
|
||||
config.clock = clock_;
|
||||
config.outgoing_transport = &transport_;
|
||||
config.local_media_ssrc = kSsrc;
|
||||
config.rtx_send_ssrc = kRtxSsrc;
|
||||
config.fec_generator = nullptr;
|
||||
config.event_log = &mock_rtc_event_log_;
|
||||
config.send_packet_observer = &send_packet_observer_;
|
||||
config.rtp_stats_callback = &mock_rtp_stats_callback_;
|
||||
config.transport_feedback_callback = &feedback_observer_;
|
||||
config.populate_network2_timestamp = false;
|
||||
config.field_trials = &trials_;
|
||||
return config;
|
||||
}
|
||||
|
||||
std::unique_ptr<RtpPacketToSend> BuildRtpPacket(bool marker_bit,
|
||||
int64_t capture_time_ms) {
|
||||
auto packet = std::make_unique<RtpPacketToSend>(&header_extensions_);
|
||||
packet->SetSsrc(kSsrc);
|
||||
packet->ReserveExtension<AbsoluteSendTime>();
|
||||
packet->ReserveExtension<TransmissionOffset>();
|
||||
packet->ReserveExtension<TransportSequenceNumber>();
|
||||
|
||||
packet->SetPayloadType(kDefaultPayloadType);
|
||||
packet->set_packet_type(RtpPacketMediaType::kVideo);
|
||||
packet->SetMarker(marker_bit);
|
||||
packet->SetTimestamp(capture_time_ms * 90);
|
||||
packet->set_capture_time_ms(capture_time_ms);
|
||||
packet->SetSequenceNumber(sequence_number_++);
|
||||
return packet;
|
||||
}
|
||||
|
||||
std::unique_ptr<RtpPacketToSend> BuildRtpPacket() {
|
||||
return BuildRtpPacket(/*marker_bit=*/true, clock_->CurrentTime().ms());
|
||||
}
|
||||
|
||||
GlobalSimulatedTimeController time_controller_;
|
||||
Clock* const clock_;
|
||||
NiceMock<MockRtcEventLog> mock_rtc_event_log_;
|
||||
StrictMock<MockStreamDataCountersCallback> mock_rtp_stats_callback_;
|
||||
NiceMock<MockSendPacketObserver> send_packet_observer_;
|
||||
NiceMock<MockTransportFeedbackObserver> feedback_observer_;
|
||||
RtpHeaderExtensionMap header_extensions_;
|
||||
TestTransport transport_;
|
||||
RtpPacketHistory packet_history_;
|
||||
FieldTrialConfig trials_;
|
||||
uint16_t sequence_number_;
|
||||
};
|
||||
|
||||
TEST_P(RtpSenderEgressTest, TransportFeedbackObserverGetsCorrectByteCount) {
|
||||
constexpr size_t kRtpOverheadBytesPerPacket = 12 + 8;
|
||||
constexpr size_t kPayloadSize = 1400;
|
||||
const uint16_t kTransportSequenceNumber = 17;
|
||||
|
||||
header_extensions_.RegisterByUri(kTransportSequenceNumberExtensionId,
|
||||
TransportSequenceNumber::kUri);
|
||||
|
||||
const size_t expected_bytes = GetParam().with_overhead
|
||||
? kPayloadSize + kRtpOverheadBytesPerPacket
|
||||
: kPayloadSize;
|
||||
|
||||
EXPECT_CALL(
|
||||
feedback_observer_,
|
||||
OnAddPacket(AllOf(
|
||||
Field(&RtpPacketSendInfo::ssrc, kSsrc),
|
||||
Field(&RtpPacketSendInfo::transport_sequence_number,
|
||||
kTransportSequenceNumber),
|
||||
Field(&RtpPacketSendInfo::rtp_sequence_number, kStartSequenceNumber),
|
||||
Field(&RtpPacketSendInfo::length, expected_bytes),
|
||||
Field(&RtpPacketSendInfo::pacing_info, PacedPacketInfo()))));
|
||||
|
||||
std::unique_ptr<RtpPacketToSend> packet = BuildRtpPacket();
|
||||
packet->SetExtension<TransportSequenceNumber>(kTransportSequenceNumber);
|
||||
packet->AllocatePayload(kPayloadSize);
|
||||
|
||||
std::unique_ptr<RtpSenderEgress> sender = CreateRtpSenderEgress();
|
||||
sender->SendPacket(packet.get(), PacedPacketInfo());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead,
|
||||
RtpSenderEgressTest,
|
||||
::testing::Values(TestConfig(false),
|
||||
TestConfig(true)));
|
||||
|
||||
} // namespace webrtc
|
||||
@ -545,44 +545,6 @@ TEST_P(RtpSenderTest, PaddingAlwaysAllowedOnAudio) {
|
||||
EXPECT_EQ(kMinPaddingSize, GenerateAndSendPadding(kMinPaddingSize - 5));
|
||||
}
|
||||
|
||||
TEST_P(RtpSenderTestWithoutPacer,
|
||||
TransportFeedbackObserverGetsCorrectByteCount) {
|
||||
constexpr size_t kRtpOverheadBytesPerPacket = 12 + 8;
|
||||
constexpr size_t kPayloadSize = 1400;
|
||||
|
||||
RtpRtcpInterface::Configuration config;
|
||||
config.clock = clock_;
|
||||
config.outgoing_transport = &transport_;
|
||||
config.local_media_ssrc = kSsrc;
|
||||
config.transport_feedback_callback = &feedback_observer_;
|
||||
config.event_log = &mock_rtc_event_log_;
|
||||
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||
config.field_trials = &field_trials_;
|
||||
rtp_sender_context_ =
|
||||
std::make_unique<RtpSenderContext>(config, &time_controller_);
|
||||
|
||||
EXPECT_TRUE(rtp_sender()->RegisterRtpHeaderExtension(
|
||||
TransportSequenceNumber::kUri, kTransportSequenceNumberExtensionId));
|
||||
|
||||
const size_t expected_bytes = GetParam().with_overhead
|
||||
? kPayloadSize + kRtpOverheadBytesPerPacket
|
||||
: kPayloadSize;
|
||||
|
||||
EXPECT_CALL(feedback_observer_,
|
||||
OnAddPacket(AllOf(
|
||||
Field(&RtpPacketSendInfo::ssrc, rtp_sender()->SSRC()),
|
||||
Field(&RtpPacketSendInfo::transport_sequence_number,
|
||||
kTransportSequenceNumber),
|
||||
Field(&RtpPacketSendInfo::rtp_sequence_number,
|
||||
rtp_sender()->SequenceNumber()),
|
||||
Field(&RtpPacketSendInfo::length, expected_bytes),
|
||||
Field(&RtpPacketSendInfo::pacing_info, PacedPacketInfo()))))
|
||||
.Times(1);
|
||||
EXPECT_EQ(rtp_sender()->ExpectedPerPacketOverhead(),
|
||||
kRtpOverheadBytesPerPacket);
|
||||
SendPacket(clock_->TimeInMilliseconds(), kPayloadSize);
|
||||
}
|
||||
|
||||
TEST_P(RtpSenderTestWithoutPacer, SendsPacketsWithTransportSequenceNumber) {
|
||||
RtpRtcpInterface::Configuration config;
|
||||
config.clock = clock_;
|
||||
|
||||
Reference in New Issue
Block a user