gecko-dev/media/webrtc/signaling/gtest/rtpsources_unittests.cpp
Sylvestre Ledru fa45a3c670 Bug 1443080 - Use the static call for static methods (not instance) r=Ehsan
MozReview-Commit-ID: JwHh4bzxuTR

--HG--
extra : rebase_source : 5f5e37517aa80c2e7b5933962178d761074886e7
2018-03-16 14:29:15 +01:00

353 lines
12 KiB
C++

#include <RtpSourceObserver.h>
#include "webrtc/modules/include/module_common_types.h"
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
using namespace mozilla;
namespace test {
class RtpSourcesTest : public ::testing::Test
{
using RtpSourceHistory = RtpSourceObserver::RtpSourceHistory;
using RtpSourceEntry = mozilla::RtpSourceObserver::RtpSourceEntry;
public:
// History Tests
// Test init happens as expected
void TestInitState() {
RtpSourceHistory history;
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
const auto& e = history.mLatestEviction;
EXPECT_FALSE(history.mHasEvictedEntry);
EXPECT_EQ(e.jitterAdjustedTimestamp, 0);
EXPECT_FALSE(e.hasAudioLevel);
EXPECT_EQ(e.audioLevel, 0);
}
// Test adding into the jitter window
void TestInsertIntoJitterWindow() {
const bool hasAudioLevel = true;
const uint8_t audioLevel = 10;
const int64_t jitter = 10;
RtpSourceHistory history;
const int64_t times[] = {100,
120,
140,
160,
180,
200,
220};
const size_t numEntries = sizeof(times) / sizeof(times[0]);
for (auto i : times) {
history.Insert(i, i + jitter, hasAudioLevel, audioLevel);
}
ASSERT_EQ(history.mDetailedHistory.size(), numEntries);
for (auto i : times) {
auto entry = history.FindClosestNotAfter(i + jitter);
ASSERT_NE(entry, nullptr);
if (entry) {
EXPECT_EQ(entry->jitterAdjustedTimestamp, i + jitter);
EXPECT_EQ(entry->hasAudioLevel, hasAudioLevel);
EXPECT_EQ(entry->audioLevel, audioLevel);
}
}
}
// Tests inserting before the jitter window, in long term history.
void TestInsertIntoLongTerm() {
RtpSourceHistory history;
constexpr int64_t timeNow = 100000;
// Should be discarded as too old
constexpr int64_t time0 = timeNow - (10 * 1000) - 1;
// Shold be commited
constexpr int64_t time1 = timeNow - (10 * 1000);
// Should be commited because it is newer
constexpr int64_t time2 = timeNow - (5 * 1000);
// Should be discarded because it is older
constexpr int64_t time3 = timeNow - (7 * 1000);
// Prune time0 should not prune time2
constexpr int64_t pruneTime0 = time2 + (10 * 1000);
// Prune time1 should prune time2
constexpr int64_t pruneTime1 = time2 + (10 * 1000) + 1;
// time0
history.Insert(timeNow, time0, true, 0);
EXPECT_TRUE(history.Empty());
EXPECT_FALSE(history.mHasEvictedEntry);
// time1
history.Insert(timeNow, time1, true, 0);
// Check that the jitter window buffer hasn't been used
EXPECT_TRUE(history.Empty());
ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time1);
EXPECT_TRUE(history.mHasEvictedEntry);
// time2
history.Insert(timeNow, time2, true, 0);
EXPECT_TRUE(history.Empty());
ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time2);
EXPECT_TRUE(history.mHasEvictedEntry);
// time3
history.Insert(timeNow, time3, true, 0);
EXPECT_TRUE(history.Empty());
ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time2);
EXPECT_TRUE(history.mHasEvictedEntry);
// pruneTime0
history.Prune(pruneTime0);
EXPECT_TRUE(history.Empty());
ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time2);
EXPECT_TRUE(history.mHasEvictedEntry);
// pruneTime1
history.Prune(pruneTime1);
EXPECT_TRUE(history.Empty());
EXPECT_FALSE(history.mHasEvictedEntry);
}
// Tests that a value inserted into the jitter window will age into long term
// storage
void TestAgeIntoLongTerm() {
RtpSourceHistory history;
constexpr int64_t jitterWindow = RtpSourceHistory::kMinJitterWindow;
constexpr int64_t jitter = jitterWindow / 2;
constexpr int64_t timeNow0 = 100000;
constexpr int64_t time0 = timeNow0;
constexpr int64_t time1 = timeNow0 + jitter;
// Prune at timeNow1 should evict time0
constexpr int64_t timeNow1 = time0 + jitterWindow + 1;
// Prune at timeNow2 should evict time1
constexpr int64_t timeNow2 = time1 + jitterWindow + 1;
// time0
history.Insert(timeNow0, time0, false, 1);
EXPECT_FALSE(history.Empty());
// Jitter window should not have grown
ASSERT_EQ(history.mMaxJitterWindow, jitterWindow);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
EXPECT_FALSE(history.mHasEvictedEntry);
// time1
history.Insert(timeNow0, time1, true, 2);
ASSERT_EQ(history.mMaxJitterWindow, jitterWindow);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(2));
EXPECT_FALSE(history.mHasEvictedEntry);
// Prune at timeNow1
history.Prune(timeNow1);
ASSERT_EQ(history.mMaxJitterWindow, jitterWindow);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
EXPECT_TRUE(history.mHasEvictedEntry);
ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time0);
ASSERT_EQ(history.mLatestEviction.hasAudioLevel, false);
ASSERT_EQ(history.mLatestEviction.audioLevel, 1);
// Prune at timeNow1
history.Prune(timeNow2);
EXPECT_EQ(history.mMaxJitterWindow, jitterWindow);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
EXPECT_TRUE(history.mHasEvictedEntry);
EXPECT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time1);
EXPECT_EQ(history.mLatestEviction.hasAudioLevel, true);
EXPECT_EQ(history.mLatestEviction.audioLevel, 2);
}
// Packets have a maximum audio level of 127
void TestMaximumAudioLevel() {
RtpSourceHistory history;
constexpr int64_t timeNow = 0;
const int64_t jitterAdjusted = timeNow + 10;
const bool hasAudioLevel = true;
const uint8_t audioLevel0 = 127;
// should result in in hasAudioLevel = false
const uint8_t audioLevel1 = 255;
// should result in in hasAudioLevel = false
const uint8_t audioLevel2 = 128;
// audio level 0
history.Insert(timeNow, jitterAdjusted, hasAudioLevel, audioLevel0);
ASSERT_FALSE(history.mHasEvictedEntry);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
{
auto* entry = history.FindClosestNotAfter(jitterAdjusted);
ASSERT_NE(entry, nullptr);
EXPECT_TRUE(entry->hasAudioLevel);
EXPECT_EQ(entry->audioLevel, audioLevel0);
}
// audio level 1
history.Insert(timeNow, jitterAdjusted, hasAudioLevel, audioLevel1);
ASSERT_FALSE(history.mHasEvictedEntry);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
{
auto* entry = history.FindClosestNotAfter(jitterAdjusted);
ASSERT_NE(entry, nullptr);
EXPECT_FALSE(entry->hasAudioLevel);
EXPECT_EQ(entry->audioLevel, audioLevel1);
}
// audio level 2
history.Insert(timeNow, jitterAdjusted, hasAudioLevel, audioLevel2);
ASSERT_FALSE(history.mHasEvictedEntry);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
{
auto* entry = history.FindClosestNotAfter(jitterAdjusted);
ASSERT_NE(entry, nullptr);
EXPECT_FALSE(entry->hasAudioLevel);
EXPECT_EQ(entry->audioLevel, audioLevel2);
}
}
void TestEmptyPrune() {
// Empty Prune
RtpSourceHistory history;
const int64_t timeNow = 0;
history.Prune(timeNow);
EXPECT_TRUE(history.Empty());
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
EXPECT_FALSE(history.mHasEvictedEntry);
}
void TestSinglePrune() {
RtpSourceHistory history;
constexpr int64_t timeNow = 10000;
constexpr int64_t jitter = RtpSourceHistory::kMinJitterWindow / 2;
const int64_t jitterAdjusted = timeNow + jitter;
history.Insert(timeNow, jitterAdjusted, 0, false);
history.Prune(timeNow + (jitter * 3) + 1);
EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
EXPECT_TRUE(history.mHasEvictedEntry);
EXPECT_EQ(jitterAdjusted, history.mLatestEviction.jitterAdjustedTimestamp);
}
// Observer tests that keys are properly handled
void TestKeyManipulation() {
constexpr unsigned int ssrc = 4682;
constexpr unsigned int csrc = 4682;
auto ssrcKey = RtpSourceObserver::GetKey(
ssrc, dom::RTCRtpSourceEntryType::Synchronization);
auto csrcKey = RtpSourceObserver::GetKey(
csrc, dom::RTCRtpSourceEntryType::Contributing);
// SSRC and CSRC keys are not the same
EXPECT_NE(ssrcKey, csrcKey);
// Keys can be reversed back to source
EXPECT_EQ(RtpSourceObserver::GetSourceFromKey(ssrcKey), ssrc);
EXPECT_EQ(RtpSourceObserver::GetSourceFromKey(csrcKey), csrc);
// Keys can be reversed back to type
EXPECT_EQ(RtpSourceObserver::GetTypeFromKey(ssrcKey),
dom::RTCRtpSourceEntryType::Synchronization);
EXPECT_EQ(RtpSourceObserver::GetTypeFromKey(csrcKey),
dom::RTCRtpSourceEntryType::Contributing);
}
// Observer a header with a single Csrc
void TestObserveOneCsrc() {
RtpSourceObserver observer;
webrtc::WebRtcRTPHeader header;
constexpr unsigned int ssrc = 857265;
constexpr unsigned int csrc = 3268365;
constexpr int64_t timestamp = 10000;
constexpr int64_t jitter = 0;
header.header.ssrc = ssrc;
header.header.numCSRCs = 1;
header.header.arrOfCSRCs[0] = csrc;
observer.OnRtpPacket(&header, timestamp, jitter);
// One for the SSRC, one for the CSRC
EXPECT_EQ(observer.mRtpSources.size(), static_cast<size_t>(2));
nsTArray<dom::RTCRtpSourceEntry> outLevels;
observer.GetRtpSources(timestamp, outLevels);
EXPECT_EQ(outLevels.Length(), static_cast<size_t>(2));
bool ssrcFound = false;
bool csrcFound = true;
for (auto& entry : outLevels) {
if (entry.mSource == ssrc) {
ssrcFound = true;
EXPECT_EQ(entry.mSourceType,
dom::RTCRtpSourceEntryType::Synchronization);
}
if (entry.mSource == csrc) {
csrcFound = true;
EXPECT_EQ(entry.mSourceType,
dom::RTCRtpSourceEntryType::Contributing);
}
}
EXPECT_TRUE(ssrcFound);
EXPECT_TRUE(csrcFound);
}
// Observer a header with two CSRCs
void TestObserveTwoCsrcs() {
RtpSourceObserver observer;
webrtc::WebRtcRTPHeader header;
constexpr unsigned int ssrc = 239485;
constexpr unsigned int csrc0 = 3425;
constexpr unsigned int csrc1 = 36457;
constexpr int64_t timestamp = 10000;
constexpr int64_t jitter = 0;
header.header.ssrc = ssrc;
header.header.numCSRCs = 2;
header.header.arrOfCSRCs[0] = csrc0;
header.header.arrOfCSRCs[1] = csrc1;
observer.OnRtpPacket(&header, timestamp, jitter);
// One for the SSRC, two for the CSRCs
EXPECT_EQ(observer.mRtpSources.size(), static_cast<size_t>(3));
nsTArray<dom::RTCRtpSourceEntry> outLevels;
observer.GetRtpSources(timestamp, outLevels);
EXPECT_EQ(outLevels.Length(), static_cast<size_t>(3));
bool ssrcFound = false;
bool csrc0Found = true;
bool csrc1Found = true;
for (auto& entry : outLevels) {
if (entry.mSource == ssrc) {
ssrcFound = true;
EXPECT_EQ(entry.mSourceType,
dom::RTCRtpSourceEntryType::Synchronization);
}
if (entry.mSource == csrc0) {
csrc0Found = true;
EXPECT_EQ(entry.mSourceType,
dom::RTCRtpSourceEntryType::Contributing);
}
if (entry.mSource == csrc1) {
csrc1Found = true;
EXPECT_EQ(entry.mSourceType,
dom::RTCRtpSourceEntryType::Contributing);
}
}
EXPECT_TRUE(ssrcFound);
EXPECT_TRUE(csrc0Found);
EXPECT_TRUE(csrc1Found);
}
// Observer a header with a CSRC with audio level extension
void TestObserveCsrcWithAudioLevel() {
RtpSourceObserver observer;
webrtc::WebRtcRTPHeader header;
}
};
TEST_F(RtpSourcesTest, TestInitState) { TestInitState(); }
TEST_F(RtpSourcesTest, TestInsertIntoJitterWindow) {
TestInsertIntoJitterWindow();
}
TEST_F(RtpSourcesTest, TestAgeIntoLongTerm){ TestAgeIntoLongTerm(); }
TEST_F(RtpSourcesTest, TestInsertIntoLongTerm) { TestInsertIntoLongTerm(); }
TEST_F(RtpSourcesTest, TestMaximumAudioLevel) { TestMaximumAudioLevel(); }
TEST_F(RtpSourcesTest, TestEmptyPrune) { TestEmptyPrune(); }
TEST_F(RtpSourcesTest, TestSinglePrune) { TestSinglePrune(); }
TEST_F(RtpSourcesTest, TestKeyManipulation) { TestKeyManipulation(); }
TEST_F(RtpSourcesTest, TestObserveOneCsrc) { TestObserveOneCsrc(); }
TEST_F(RtpSourcesTest, TestObserveTwoCsrcs) { TestObserveTwoCsrcs(); }
TEST_F(RtpSourcesTest, TestObserveCsrcWithAudioLevel) {
TestObserveCsrcWithAudioLevel();
}
}