Developing NetEqImpl unit tests

Adding option to use mock or real objects instead of mocks.
This will help future testing efforts, where each test case can
select whether a mock or a real object should be used.

Adding new test InsertPacketsUntilBufferIsFull.

Removing a few uniteresting mock call warning.

R=turaj@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/9839004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5684 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrik.lundin@webrtc.org 2014-03-12 05:55:10 +00:00
parent 10bd88e2b5
commit 04ea23234a

View File

@ -48,21 +48,92 @@ int DeletePacketsAndReturnOk(PacketList* packet_list) {
class NetEqImplTest : public ::testing::Test {
protected:
static const int kInitSampleRateHz = 8000;
NetEqImplTest() {
buffer_level_filter_ = new MockBufferLevelFilter;
decoder_database_ = new MockDecoderDatabase;
delay_peak_detector_ = new MockDelayPeakDetector;
EXPECT_CALL(*delay_peak_detector_, Reset()).Times(1);
delay_manager_ = new MockDelayManager(NetEq::kMaxNumPacketsInBuffer,
delay_peak_detector_);
dtmf_buffer_ = new MockDtmfBuffer(kInitSampleRateHz);
dtmf_tone_generator_ = new MockDtmfToneGenerator;
packet_buffer_ = new MockPacketBuffer(NetEq::kMaxNumPacketsInBuffer,
NetEq::kMaxBytesInBuffer);
payload_splitter_ = new MockPayloadSplitter;
NetEqImplTest()
: neteq_(NULL),
mock_buffer_level_filter_(NULL),
buffer_level_filter_(NULL),
use_mock_buffer_level_filter_(true),
mock_decoder_database_(NULL),
decoder_database_(NULL),
use_mock_decoder_database_(true),
mock_delay_peak_detector_(NULL),
delay_peak_detector_(NULL),
use_mock_delay_peak_detector_(true),
mock_delay_manager_(NULL),
delay_manager_(NULL),
use_mock_delay_manager_(true),
mock_dtmf_buffer_(NULL),
dtmf_buffer_(NULL),
use_mock_dtmf_buffer_(true),
mock_dtmf_tone_generator_(NULL),
dtmf_tone_generator_(NULL),
use_mock_dtmf_tone_generator_(true),
mock_packet_buffer_(NULL),
packet_buffer_(NULL),
use_mock_packet_buffer_(true),
mock_payload_splitter_(NULL),
payload_splitter_(NULL),
use_mock_payload_splitter_(true),
timestamp_scaler_(NULL) {}
void CreateInstance() {
if (use_mock_buffer_level_filter_) {
mock_buffer_level_filter_ = new MockBufferLevelFilter;
buffer_level_filter_ = mock_buffer_level_filter_;
} else {
buffer_level_filter_ = new BufferLevelFilter;
}
if (use_mock_decoder_database_) {
mock_decoder_database_ = new MockDecoderDatabase;
EXPECT_CALL(*mock_decoder_database_, GetActiveCngDecoder())
.WillOnce(ReturnNull());
decoder_database_ = mock_decoder_database_;
} else {
decoder_database_ = new DecoderDatabase;
}
if (use_mock_delay_peak_detector_) {
mock_delay_peak_detector_ = new MockDelayPeakDetector;
EXPECT_CALL(*mock_delay_peak_detector_, Reset()).Times(1);
delay_peak_detector_ = mock_delay_peak_detector_;
} else {
delay_peak_detector_ = new DelayPeakDetector;
}
if (use_mock_delay_manager_) {
mock_delay_manager_ = new MockDelayManager(NetEq::kMaxNumPacketsInBuffer,
delay_peak_detector_);
EXPECT_CALL(*mock_delay_manager_, set_streaming_mode(false)).Times(1);
delay_manager_ = mock_delay_manager_;
} else {
delay_manager_ =
new DelayManager(NetEq::kMaxNumPacketsInBuffer, delay_peak_detector_);
}
if (use_mock_dtmf_buffer_) {
mock_dtmf_buffer_ = new MockDtmfBuffer(kInitSampleRateHz);
dtmf_buffer_ = mock_dtmf_buffer_;
} else {
dtmf_buffer_ = new DtmfBuffer(kInitSampleRateHz);
}
if (use_mock_dtmf_tone_generator_) {
mock_dtmf_tone_generator_ = new MockDtmfToneGenerator;
dtmf_tone_generator_ = mock_dtmf_tone_generator_;
} else {
dtmf_tone_generator_ = new DtmfToneGenerator;
}
if (use_mock_packet_buffer_) {
mock_packet_buffer_ = new MockPacketBuffer(NetEq::kMaxNumPacketsInBuffer,
NetEq::kMaxBytesInBuffer);
packet_buffer_ = mock_packet_buffer_;
} else {
packet_buffer_ = new PacketBuffer(NetEq::kMaxNumPacketsInBuffer,
NetEq::kMaxBytesInBuffer);
}
if (use_mock_payload_splitter_) {
mock_payload_splitter_ = new MockPayloadSplitter;
payload_splitter_ = mock_payload_splitter_;
} else {
payload_splitter_ = new PayloadSplitter;
}
timestamp_scaler_ = new TimestampScaler(*decoder_database_);
EXPECT_CALL(*decoder_database_, GetActiveCngDecoder())
.WillOnce(ReturnNull());
AccelerateFactory* accelerate_factory = new AccelerateFactory;
ExpandFactory* expand_factory = new ExpandFactory;
PreemptiveExpandFactory* preemptive_expand_factory =
@ -81,28 +152,71 @@ class NetEqImplTest : public ::testing::Test {
accelerate_factory,
expand_factory,
preemptive_expand_factory);
ASSERT_TRUE(neteq_ != NULL);
}
void UseNoMocks() {
ASSERT_TRUE(neteq_ == NULL) << "Must call UseNoMocks before CreateInstance";
use_mock_buffer_level_filter_ = false;
use_mock_decoder_database_ = false;
use_mock_delay_peak_detector_ = false;
use_mock_delay_manager_ = false;
use_mock_dtmf_buffer_ = false;
use_mock_dtmf_tone_generator_ = false;
use_mock_packet_buffer_ = false;
use_mock_payload_splitter_ = false;
}
virtual ~NetEqImplTest() {
EXPECT_CALL(*buffer_level_filter_, Die()).Times(1);
EXPECT_CALL(*decoder_database_, Die()).Times(1);
EXPECT_CALL(*delay_manager_, Die()).Times(1);
EXPECT_CALL(*delay_peak_detector_, Die()).Times(1);
EXPECT_CALL(*dtmf_buffer_, Die()).Times(1);
EXPECT_CALL(*dtmf_tone_generator_, Die()).Times(1);
EXPECT_CALL(*packet_buffer_, Die()).Times(1);
if (use_mock_buffer_level_filter_) {
EXPECT_CALL(*mock_buffer_level_filter_, Die()).Times(1);
}
if (use_mock_decoder_database_) {
EXPECT_CALL(*mock_decoder_database_, Die()).Times(1);
}
if (use_mock_delay_manager_) {
EXPECT_CALL(*mock_delay_manager_, Die()).Times(1);
}
if (use_mock_delay_peak_detector_) {
EXPECT_CALL(*mock_delay_peak_detector_, Die()).Times(1);
}
if (use_mock_dtmf_buffer_) {
EXPECT_CALL(*mock_dtmf_buffer_, Die()).Times(1);
}
if (use_mock_dtmf_tone_generator_) {
EXPECT_CALL(*mock_dtmf_tone_generator_, Die()).Times(1);
}
if (use_mock_packet_buffer_) {
EXPECT_CALL(*mock_packet_buffer_, Die()).Times(1);
}
delete neteq_;
}
NetEqImpl* neteq_;
MockBufferLevelFilter* buffer_level_filter_;
MockDecoderDatabase* decoder_database_;
MockDelayPeakDetector* delay_peak_detector_;
MockDelayManager* delay_manager_;
MockDtmfBuffer* dtmf_buffer_;
MockDtmfToneGenerator* dtmf_tone_generator_;
MockPacketBuffer* packet_buffer_;
MockPayloadSplitter* payload_splitter_;
MockBufferLevelFilter* mock_buffer_level_filter_;
BufferLevelFilter* buffer_level_filter_;
bool use_mock_buffer_level_filter_;
MockDecoderDatabase* mock_decoder_database_;
DecoderDatabase* decoder_database_;
bool use_mock_decoder_database_;
MockDelayPeakDetector* mock_delay_peak_detector_;
DelayPeakDetector* delay_peak_detector_;
bool use_mock_delay_peak_detector_;
MockDelayManager* mock_delay_manager_;
DelayManager* delay_manager_;
bool use_mock_delay_manager_;
MockDtmfBuffer* mock_dtmf_buffer_;
DtmfBuffer* dtmf_buffer_;
bool use_mock_dtmf_buffer_;
MockDtmfToneGenerator* mock_dtmf_tone_generator_;
DtmfToneGenerator* dtmf_tone_generator_;
bool use_mock_dtmf_tone_generator_;
MockPacketBuffer* mock_packet_buffer_;
PacketBuffer* packet_buffer_;
bool use_mock_packet_buffer_;
MockPayloadSplitter* mock_payload_splitter_;
PayloadSplitter* payload_splitter_;
bool use_mock_payload_splitter_;
TimestampScaler* timestamp_scaler_;
};
@ -115,23 +229,25 @@ TEST(NetEq, CreateAndDestroy) {
}
TEST_F(NetEqImplTest, RegisterPayloadType) {
CreateInstance();
uint8_t rtp_payload_type = 0;
NetEqDecoder codec_type = kDecoderPCMu;
EXPECT_CALL(*decoder_database_,
EXPECT_CALL(*mock_decoder_database_,
RegisterPayload(rtp_payload_type, codec_type));
neteq_->RegisterPayloadType(codec_type, rtp_payload_type);
}
TEST_F(NetEqImplTest, RemovePayloadType) {
CreateInstance();
uint8_t rtp_payload_type = 0;
EXPECT_CALL(*decoder_database_,
Remove(rtp_payload_type))
EXPECT_CALL(*mock_decoder_database_, Remove(rtp_payload_type))
.WillOnce(Return(DecoderDatabase::kDecoderNotFound));
// Check that kFail is returned when database returns kDecoderNotFound.
EXPECT_EQ(NetEq::kFail, neteq_->RemovePayloadType(rtp_payload_type));
}
TEST_F(NetEqImplTest, InsertPacket) {
CreateInstance();
const int kPayloadLength = 100;
const uint8_t kPayloadType = 0;
const uint16_t kFirstSequenceNumber = 0x1234;
@ -162,31 +278,33 @@ TEST_F(NetEqImplTest, InsertPacket) {
EXPECT_CALL(mock_decoder, Die()).Times(1); // Called when deleted.
// Expectations for decoder database.
EXPECT_CALL(*decoder_database_, IsRed(kPayloadType))
EXPECT_CALL(*mock_decoder_database_, IsRed(kPayloadType))
.WillRepeatedly(Return(false)); // This is not RED.
EXPECT_CALL(*decoder_database_, CheckPayloadTypes(_))
EXPECT_CALL(*mock_decoder_database_, CheckPayloadTypes(_))
.Times(2)
.WillRepeatedly(Return(DecoderDatabase::kOK)); // Payload type is valid.
EXPECT_CALL(*decoder_database_, IsDtmf(kPayloadType))
EXPECT_CALL(*mock_decoder_database_, IsDtmf(kPayloadType))
.WillRepeatedly(Return(false)); // This is not DTMF.
EXPECT_CALL(*decoder_database_, GetDecoder(kPayloadType))
EXPECT_CALL(*mock_decoder_database_, GetDecoder(kPayloadType))
.Times(3)
.WillRepeatedly(Return(&mock_decoder));
EXPECT_CALL(*decoder_database_, IsComfortNoise(kPayloadType))
EXPECT_CALL(*mock_decoder_database_, IsComfortNoise(kPayloadType))
.WillRepeatedly(Return(false)); // This is not CNG.
DecoderDatabase::DecoderInfo info;
info.codec_type = kDecoderPCMu;
EXPECT_CALL(*decoder_database_, GetDecoderInfo(kPayloadType))
EXPECT_CALL(*mock_decoder_database_, GetDecoderInfo(kPayloadType))
.WillRepeatedly(Return(&info));
// Expectations for packet buffer.
EXPECT_CALL(*packet_buffer_, NumPacketsInBuffer())
EXPECT_CALL(*mock_packet_buffer_, NumPacketsInBuffer())
.WillOnce(Return(0)) // First packet.
.WillOnce(Return(1)) // Second packet.
.WillOnce(Return(2)); // Second packet, checking after it was inserted.
EXPECT_CALL(*packet_buffer_, Flush())
EXPECT_CALL(*mock_packet_buffer_, Empty())
.WillOnce(Return(false)); // Called once after first packet is inserted.
EXPECT_CALL(*mock_packet_buffer_, Flush())
.Times(1);
EXPECT_CALL(*packet_buffer_, InsertPacketList(_, _, _, _))
EXPECT_CALL(*mock_packet_buffer_, InsertPacketList(_, _, _, _))
.Times(2)
.WillRepeatedly(DoAll(SetArgPointee<2>(kPayloadType),
WithArg<0>(Invoke(DeletePacketsAndReturnOk))));
@ -194,12 +312,12 @@ TEST_F(NetEqImplTest, InsertPacket) {
// index) is a pointer, and the variable pointed to is set to kPayloadType.
// Also invoke the function DeletePacketsAndReturnOk to properly delete all
// packets in the list (to avoid memory leaks in the test).
EXPECT_CALL(*packet_buffer_, NextRtpHeader())
EXPECT_CALL(*mock_packet_buffer_, NextRtpHeader())
.Times(1)
.WillOnce(Return(&rtp_header.header));
// Expectations for DTMF buffer.
EXPECT_CALL(*dtmf_buffer_, Flush())
EXPECT_CALL(*mock_dtmf_buffer_, Flush())
.Times(1);
// Expectations for delay manager.
@ -207,23 +325,25 @@ TEST_F(NetEqImplTest, InsertPacket) {
// All expectations within this block must be called in this specific order.
InSequence sequence; // Dummy variable.
// Expectations when the first packet is inserted.
EXPECT_CALL(*delay_manager_, LastDecoderType(kDecoderPCMu))
EXPECT_CALL(*mock_delay_manager_, LastDecoderType(kDecoderPCMu))
.Times(1);
EXPECT_CALL(*delay_manager_, last_pack_cng_or_dtmf())
EXPECT_CALL(*mock_delay_manager_, last_pack_cng_or_dtmf())
.Times(2)
.WillRepeatedly(Return(-1));
EXPECT_CALL(*delay_manager_, set_last_pack_cng_or_dtmf(0))
EXPECT_CALL(*mock_delay_manager_, set_last_pack_cng_or_dtmf(0))
.Times(1);
EXPECT_CALL(*delay_manager_, ResetPacketIatCount()).Times(1);
EXPECT_CALL(*mock_delay_manager_, ResetPacketIatCount()).Times(1);
// Expectations when the second packet is inserted. Slightly different.
EXPECT_CALL(*delay_manager_, LastDecoderType(kDecoderPCMu))
EXPECT_CALL(*mock_delay_manager_, LastDecoderType(kDecoderPCMu))
.Times(1);
EXPECT_CALL(*delay_manager_, last_pack_cng_or_dtmf())
EXPECT_CALL(*mock_delay_manager_, last_pack_cng_or_dtmf())
.WillOnce(Return(0));
EXPECT_CALL(*mock_delay_manager_, SetPacketAudioLength(30))
.WillOnce(Return(0));
}
// Expectations for payload splitter.
EXPECT_CALL(*payload_splitter_, SplitAudio(_, _))
EXPECT_CALL(*mock_payload_splitter_, SplitAudio(_, _))
.Times(2)
.WillRepeatedly(Return(PayloadSplitter::kOK));
@ -237,4 +357,43 @@ TEST_F(NetEqImplTest, InsertPacket) {
kFirstReceiveTime + 155);
}
TEST_F(NetEqImplTest, InsertPacketsUntilBufferIsFull) {
UseNoMocks();
CreateInstance();
const int kPayloadLengthSamples = 80;
const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples; // PCM 16-bit.
const uint8_t kPayloadType = 17; // Just an arbitrary number.
const uint32_t kReceiveTime = 17; // Value doesn't matter for this test.
uint8_t payload[kPayloadLengthBytes] = {0};
WebRtcRTPHeader rtp_header;
rtp_header.header.payloadType = kPayloadType;
rtp_header.header.sequenceNumber = 0x1234;
rtp_header.header.timestamp = 0x12345678;
rtp_header.header.ssrc = 0x87654321;
EXPECT_EQ(NetEq::kOK,
neteq_->RegisterPayloadType(kDecoderPCM16B, kPayloadType));
// Insert packets. The buffer should not flush.
for (int i = 1; i <= NetEq::kMaxNumPacketsInBuffer; ++i) {
EXPECT_EQ(NetEq::kOK,
neteq_->InsertPacket(
rtp_header, payload, kPayloadLengthBytes, kReceiveTime));
rtp_header.header.timestamp += kPayloadLengthSamples;
rtp_header.header.sequenceNumber += 1;
EXPECT_EQ(i, packet_buffer_->NumPacketsInBuffer());
}
// Insert one more packet and make sure the buffer got flushed. That is, it
// should only hold one single packet.
EXPECT_EQ(NetEq::kOK,
neteq_->InsertPacket(
rtp_header, payload, kPayloadLengthBytes, kReceiveTime));
EXPECT_EQ(1, packet_buffer_->NumPacketsInBuffer());
const RTPHeader* test_header = packet_buffer_->NextRtpHeader();
EXPECT_EQ(rtp_header.header.timestamp, test_header->timestamp);
EXPECT_EQ(rtp_header.header.sequenceNumber, test_header->sequenceNumber);
}
} // namespace webrtc