Add FlexfecReceiver unit test for infinite recovery loop.

This CL adds unit tests to the FlexfecReceiver, verifying that the
infinite recovery loop described in
https://codereview.webrtc.org/2867943003/ is tested for.

BUG=webrtc:5654

Review-Url: https://codereview.webrtc.org/2895083002
Cr-Commit-Position: refs/heads/master@{#18240}
This commit is contained in:
brandtr 2017-05-23 08:38:43 -07:00 committed by Commit bot
parent cc8b14b1ec
commit f27c5b8d6e

View File

@ -301,10 +301,17 @@ TEST_F(FlexfecReceiverTest, DoesNotCallbackTwice) {
Args<0, 1>(ElementsAreArray((*media_it)->data, (*media_it)->length)));
receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
// Receive FEC packet again.
// Receive the FEC packet again, but do not call back.
receiver_.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
// Do not call back again.
// Receive the first media packet again, but do not call back.
media_it = media_packets.begin();
receiver_.OnRtpPacket(ParsePacket(**media_it));
// Receive the second media packet again (the one recovered above),
// but do not call back again.
media_it++;
receiver_.OnRtpPacket(ParsePacket(**media_it));
}
// Here we are implicitly assuming packet masks that are suitable for
@ -464,6 +471,72 @@ TEST_F(FlexfecReceiverTest, RecoversWithMediaPacketsOutOfOrder) {
}
}
// Recovered media packets may be fed back into the FlexfecReceiver by the
// callback. This test ensures the idempotency of such a situation.
TEST_F(FlexfecReceiverTest, RecoveryCallbackDoesNotLoopInfinitely) {
class LoopbackRecoveredPacketReceiver : public RecoveredPacketReceiver {
public:
const int kMaxRecursionDepth = 10;
LoopbackRecoveredPacketReceiver()
: receiver_(nullptr),
did_receive_call_back_(false),
recursion_depth_(0),
deep_recursion_(false) {}
void SetReceiver(FlexfecReceiver* receiver) { receiver_ = receiver; }
bool DidReceiveCallback() const { return did_receive_call_back_; }
bool DeepRecursion() const { return deep_recursion_; }
// Implements RecoveredPacketReceiver.
void OnRecoveredPacket(const uint8_t* packet, size_t length) {
RtpPacketReceived parsed_packet;
EXPECT_TRUE(parsed_packet.Parse(packet, length));
did_receive_call_back_ = true;
if (recursion_depth_ > kMaxRecursionDepth) {
deep_recursion_ = true;
return;
}
++recursion_depth_;
RTC_DCHECK(receiver_);
receiver_->OnRtpPacket(parsed_packet);
--recursion_depth_;
}
private:
FlexfecReceiver* receiver_;
bool did_receive_call_back_;
int recursion_depth_;
bool deep_recursion_;
} loopback_recovered_packet_receiver;
// Feed recovered packets back into |receiver|.
FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
&loopback_recovered_packet_receiver);
loopback_recovered_packet_receiver.SetReceiver(&receiver);
const size_t kNumMediaPackets = 2;
const size_t kNumFecPackets = 1;
PacketList media_packets;
PacketizeFrame(kNumMediaPackets, 0, &media_packets);
std::list<Packet*> fec_packets = EncodeFec(media_packets, kNumFecPackets);
// Receive first media packet but drop second.
auto media_it = media_packets.begin();
receiver.OnRtpPacket(ParsePacket(**media_it));
// Receive FEC packet and verify that a packet was recovered.
auto fec_it = fec_packets.begin();
std::unique_ptr<Packet> packet_with_rtp_header =
packet_generator_.BuildFlexfecPacket(**fec_it);
receiver.OnRtpPacket(ParsePacket(*packet_with_rtp_header));
EXPECT_TRUE(loopback_recovered_packet_receiver.DidReceiveCallback());
EXPECT_FALSE(loopback_recovered_packet_receiver.DeepRecursion());
}
TEST_F(FlexfecReceiverTest, CalculatesNumberOfPackets) {
const size_t kNumMediaPackets = 2;
const size_t kNumFecPackets = 1;