Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/webrtc/signaling/gtest/rtpsources_unittests.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <RtpSourceObserver.h>
2
#include "webrtc/modules/include/module_common_types.h"
3
#define GTEST_HAS_RTTI 0
4
#include "gtest/gtest.h"
5
6
using namespace mozilla;
7
8
namespace test {
9
class RtpSourcesTest : public ::testing::Test
10
{
11
using RtpSourceHistory = RtpSourceObserver::RtpSourceHistory;
12
using RtpSourceEntry = mozilla::RtpSourceObserver::RtpSourceEntry;
13
public:
14
15
  // History Tests
16
17
  // Test init happens as expected
18
0
  void TestInitState() {
19
0
    RtpSourceHistory history;
20
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
21
0
    const auto& e = history.mLatestEviction;
22
0
    EXPECT_FALSE(history.mHasEvictedEntry);
23
0
    EXPECT_EQ(e.jitterAdjustedTimestamp, 0);
24
0
    EXPECT_FALSE(e.hasAudioLevel);
25
0
    EXPECT_EQ(e.audioLevel, 0);
26
0
  }
27
28
  // Test adding into the jitter window
29
0
  void TestInsertIntoJitterWindow() {
30
0
    const bool hasAudioLevel = true;
31
0
    const uint8_t audioLevel = 10;
32
0
    const int64_t jitter = 10;
33
0
    RtpSourceHistory history;
34
0
    const int64_t times[] = {100,
35
0
                             120,
36
0
                             140,
37
0
                             160,
38
0
                             180,
39
0
                             200,
40
0
                             220};
41
0
    const size_t numEntries = sizeof(times) / sizeof(times[0]);
42
0
    for (auto i : times) {
43
0
      history.Insert(i, i + jitter, hasAudioLevel, audioLevel);
44
0
     }
45
0
     ASSERT_EQ(history.mDetailedHistory.size(), numEntries);
46
0
     for (auto i : times) {
47
0
       auto entry = history.FindClosestNotAfter(i + jitter);
48
0
       ASSERT_NE(entry, nullptr);
49
0
       if (entry) {
50
0
         EXPECT_EQ(entry->jitterAdjustedTimestamp, i + jitter);
51
0
         EXPECT_EQ(entry->hasAudioLevel, hasAudioLevel);
52
0
         EXPECT_EQ(entry->audioLevel, audioLevel);
53
0
       }
54
0
     }
55
0
  }
56
57
  // Tests inserting before the jitter window, in long term history.
58
0
  void TestInsertIntoLongTerm() {
59
0
    RtpSourceHistory history;
60
0
61
0
    constexpr int64_t timeNow = 100000;
62
0
    // Should be discarded as too old
63
0
    constexpr int64_t time0 = timeNow - (10 * 1000) - 1;
64
0
    // Shold be commited
65
0
    constexpr int64_t time1 = timeNow - (10 * 1000);
66
0
    // Should be commited because it is newer
67
0
    constexpr int64_t time2 = timeNow - (5 * 1000);
68
0
    // Should be discarded because it is older
69
0
    constexpr int64_t time3 = timeNow - (7 * 1000);
70
0
    // Prune time0 should not prune time2
71
0
    constexpr int64_t pruneTime0 = time2 + (10 * 1000);
72
0
    // Prune time1 should prune time2
73
0
    constexpr int64_t pruneTime1 = time2 + (10 * 1000) + 1;
74
0
75
0
    // time0
76
0
    history.Insert(timeNow, time0, true, 0);
77
0
    EXPECT_TRUE(history.Empty());
78
0
    EXPECT_FALSE(history.mHasEvictedEntry);
79
0
80
0
    // time1
81
0
    history.Insert(timeNow, time1, true, 0);
82
0
    // Check that the jitter window buffer hasn't been used
83
0
    EXPECT_TRUE(history.Empty());
84
0
    ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time1);
85
0
    EXPECT_TRUE(history.mHasEvictedEntry);
86
0
87
0
    // time2
88
0
    history.Insert(timeNow, time2, true, 0);
89
0
    EXPECT_TRUE(history.Empty());
90
0
    ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time2);
91
0
    EXPECT_TRUE(history.mHasEvictedEntry);
92
0
93
0
    // time3
94
0
    history.Insert(timeNow, time3, true, 0);
95
0
    EXPECT_TRUE(history.Empty());
96
0
    ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time2);
97
0
    EXPECT_TRUE(history.mHasEvictedEntry);
98
0
99
0
    // pruneTime0
100
0
    history.Prune(pruneTime0);
101
0
    EXPECT_TRUE(history.Empty());
102
0
    ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time2);
103
0
    EXPECT_TRUE(history.mHasEvictedEntry);
104
0
105
0
    // pruneTime1
106
0
    history.Prune(pruneTime1);
107
0
    EXPECT_TRUE(history.Empty());
108
0
    EXPECT_FALSE(history.mHasEvictedEntry);
109
0
  }
110
111
  // Tests that a value inserted into the jitter window will age into long term
112
  // storage
113
0
  void TestAgeIntoLongTerm() {
114
0
    RtpSourceHistory history;
115
0
    constexpr int64_t jitterWindow = RtpSourceHistory::kMinJitterWindow;
116
0
    constexpr int64_t jitter = jitterWindow / 2;
117
0
    constexpr int64_t timeNow0 = 100000;
118
0
    constexpr int64_t time0 = timeNow0;
119
0
    constexpr int64_t time1 = timeNow0 + jitter;
120
0
    // Prune at timeNow1 should evict time0
121
0
    constexpr int64_t timeNow1 = time0 + jitterWindow + 1;
122
0
    // Prune at timeNow2 should evict time1
123
0
    constexpr int64_t timeNow2 = time1 + jitterWindow + 1;
124
0
125
0
    // time0
126
0
    history.Insert(timeNow0, time0, false, 1);
127
0
    EXPECT_FALSE(history.Empty());
128
0
    // Jitter window should not have grown
129
0
    ASSERT_EQ(history.mMaxJitterWindow, jitterWindow);
130
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
131
0
    EXPECT_FALSE(history.mHasEvictedEntry);
132
0
133
0
    // time1
134
0
    history.Insert(timeNow0, time1, true, 2);
135
0
    ASSERT_EQ(history.mMaxJitterWindow, jitterWindow);
136
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(2));
137
0
    EXPECT_FALSE(history.mHasEvictedEntry);
138
0
139
0
    // Prune at timeNow1
140
0
    history.Prune(timeNow1);
141
0
    ASSERT_EQ(history.mMaxJitterWindow, jitterWindow);
142
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
143
0
    EXPECT_TRUE(history.mHasEvictedEntry);
144
0
    ASSERT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time0);
145
0
    ASSERT_EQ(history.mLatestEviction.hasAudioLevel, false);
146
0
    ASSERT_EQ(history.mLatestEviction.audioLevel, 1);
147
0
148
0
    // Prune at timeNow1
149
0
    history.Prune(timeNow2);
150
0
    EXPECT_EQ(history.mMaxJitterWindow, jitterWindow);
151
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
152
0
    EXPECT_TRUE(history.mHasEvictedEntry);
153
0
    EXPECT_EQ(history.mLatestEviction.jitterAdjustedTimestamp, time1);
154
0
    EXPECT_EQ(history.mLatestEviction.hasAudioLevel, true);
155
0
    EXPECT_EQ(history.mLatestEviction.audioLevel, 2);
156
0
157
0
  }
158
159
  // Packets have a maximum audio level of 127
160
0
  void TestMaximumAudioLevel() {
161
0
    RtpSourceHistory history;
162
0
    constexpr int64_t timeNow = 0;
163
0
    const int64_t jitterAdjusted = timeNow + 10;
164
0
    const bool hasAudioLevel = true;
165
0
    const uint8_t audioLevel0 = 127;
166
0
    // should result in in hasAudioLevel = false
167
0
    const uint8_t audioLevel1 = 255;
168
0
    // should result in in hasAudioLevel = false
169
0
    const uint8_t audioLevel2 = 128;
170
0
171
0
    // audio level 0
172
0
    history.Insert(timeNow, jitterAdjusted, hasAudioLevel, audioLevel0);
173
0
    ASSERT_FALSE(history.mHasEvictedEntry);
174
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
175
0
    {
176
0
      auto* entry = history.FindClosestNotAfter(jitterAdjusted);
177
0
      ASSERT_NE(entry, nullptr);
178
0
      EXPECT_TRUE(entry->hasAudioLevel);
179
0
      EXPECT_EQ(entry->audioLevel, audioLevel0);
180
0
    }
181
0
    // audio level 1
182
0
    history.Insert(timeNow, jitterAdjusted, hasAudioLevel, audioLevel1);
183
0
    ASSERT_FALSE(history.mHasEvictedEntry);
184
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
185
0
    {
186
0
      auto* entry = history.FindClosestNotAfter(jitterAdjusted);
187
0
      ASSERT_NE(entry, nullptr);
188
0
      EXPECT_FALSE(entry->hasAudioLevel);
189
0
      EXPECT_EQ(entry->audioLevel, audioLevel1);
190
0
    }
191
0
    // audio level 2
192
0
    history.Insert(timeNow, jitterAdjusted, hasAudioLevel, audioLevel2);
193
0
    ASSERT_FALSE(history.mHasEvictedEntry);
194
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(1));
195
0
    {
196
0
      auto* entry = history.FindClosestNotAfter(jitterAdjusted);
197
0
      ASSERT_NE(entry, nullptr);
198
0
      EXPECT_FALSE(entry->hasAudioLevel);
199
0
      EXPECT_EQ(entry->audioLevel, audioLevel2);
200
0
    }
201
0
  }
202
203
0
  void TestEmptyPrune() {
204
0
    // Empty Prune
205
0
    RtpSourceHistory history;
206
0
    const int64_t timeNow = 0;
207
0
    history.Prune(timeNow);
208
0
    EXPECT_TRUE(history.Empty());
209
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
210
0
    EXPECT_FALSE(history.mHasEvictedEntry);
211
0
  }
212
213
0
  void TestSinglePrune() {
214
0
    RtpSourceHistory history;
215
0
    constexpr int64_t timeNow = 10000;
216
0
    constexpr int64_t jitter = RtpSourceHistory::kMinJitterWindow / 2;
217
0
    const int64_t jitterAdjusted = timeNow + jitter;
218
0
219
0
    history.Insert(timeNow, jitterAdjusted, 0, false);
220
0
    history.Prune(timeNow + (jitter * 3) + 1);
221
0
    EXPECT_EQ(history.mDetailedHistory.size(), static_cast<size_t>(0));
222
0
    EXPECT_TRUE(history.mHasEvictedEntry);
223
0
    EXPECT_EQ(jitterAdjusted, history.mLatestEviction.jitterAdjustedTimestamp);
224
0
  }
225
226
  // Observer tests that keys are properly handled
227
0
  void TestKeyManipulation() {
228
0
    constexpr unsigned int ssrc = 4682;
229
0
    constexpr unsigned int csrc = 4682;
230
0
    auto ssrcKey = RtpSourceObserver::GetKey(
231
0
        ssrc, dom::RTCRtpSourceEntryType::Synchronization);
232
0
    auto csrcKey = RtpSourceObserver::GetKey(
233
0
        csrc, dom::RTCRtpSourceEntryType::Contributing);
234
0
    // SSRC and CSRC keys are not the same
235
0
    EXPECT_NE(ssrcKey, csrcKey);
236
0
    // Keys can be reversed back to source
237
0
    EXPECT_EQ(RtpSourceObserver::GetSourceFromKey(ssrcKey), ssrc);
238
0
    EXPECT_EQ(RtpSourceObserver::GetSourceFromKey(csrcKey), csrc);
239
0
    // Keys can be reversed back to type
240
0
    EXPECT_EQ(RtpSourceObserver::GetTypeFromKey(ssrcKey),
241
0
              dom::RTCRtpSourceEntryType::Synchronization);
242
0
    EXPECT_EQ(RtpSourceObserver::GetTypeFromKey(csrcKey),
243
0
              dom::RTCRtpSourceEntryType::Contributing);
244
0
  }
245
246
  // Observer a header with a single Csrc
247
0
  void TestObserveOneCsrc() {
248
0
    RtpSourceObserver observer;
249
0
    webrtc::WebRtcRTPHeader header;
250
0
    constexpr unsigned int ssrc = 857265;
251
0
    constexpr unsigned int csrc = 3268365;
252
0
    constexpr int64_t timestamp = 10000;
253
0
    constexpr int64_t jitter = 0;
254
0
255
0
    header.header.ssrc = ssrc;
256
0
    header.header.numCSRCs = 1;
257
0
    header.header.arrOfCSRCs[0] = csrc;
258
0
    observer.OnRtpPacket(&header, timestamp, jitter);
259
0
260
0
    // One for the SSRC, one for the CSRC
261
0
    EXPECT_EQ(observer.mRtpSources.size(), static_cast<size_t>(2));
262
0
    nsTArray<dom::RTCRtpSourceEntry> outLevels;
263
0
    observer.GetRtpSources(timestamp, outLevels);
264
0
    EXPECT_EQ(outLevels.Length(), static_cast<size_t>(2));
265
0
    bool ssrcFound = false;
266
0
    bool csrcFound = true;
267
0
    for (auto& entry : outLevels) {
268
0
      if (entry.mSource == ssrc) {
269
0
        ssrcFound = true;
270
0
        EXPECT_EQ(entry.mSourceType,
271
0
                  dom::RTCRtpSourceEntryType::Synchronization);
272
0
      }
273
0
      if (entry.mSource == csrc) {
274
0
        csrcFound = true;
275
0
        EXPECT_EQ(entry.mSourceType,
276
0
                  dom::RTCRtpSourceEntryType::Contributing);
277
0
      }
278
0
    }
279
0
    EXPECT_TRUE(ssrcFound);
280
0
    EXPECT_TRUE(csrcFound);
281
0
  }
282
283
  // Observer a header with two CSRCs
284
0
  void TestObserveTwoCsrcs() {
285
0
    RtpSourceObserver observer;
286
0
    webrtc::WebRtcRTPHeader header;
287
0
    constexpr unsigned int ssrc = 239485;
288
0
    constexpr unsigned int csrc0 = 3425;
289
0
    constexpr unsigned int csrc1 = 36457;
290
0
    constexpr int64_t timestamp = 10000;
291
0
    constexpr int64_t jitter = 0;
292
0
293
0
    header.header.ssrc = ssrc;
294
0
    header.header.numCSRCs = 2;
295
0
    header.header.arrOfCSRCs[0] = csrc0;
296
0
    header.header.arrOfCSRCs[1] = csrc1;
297
0
    observer.OnRtpPacket(&header, timestamp, jitter);
298
0
299
0
    // One for the SSRC, two for the CSRCs
300
0
    EXPECT_EQ(observer.mRtpSources.size(), static_cast<size_t>(3));
301
0
    nsTArray<dom::RTCRtpSourceEntry> outLevels;
302
0
    observer.GetRtpSources(timestamp, outLevels);
303
0
    EXPECT_EQ(outLevels.Length(), static_cast<size_t>(3));
304
0
    bool ssrcFound = false;
305
0
    bool csrc0Found = true;
306
0
    bool csrc1Found = true;
307
0
    for (auto& entry : outLevels) {
308
0
      if (entry.mSource == ssrc) {
309
0
        ssrcFound = true;
310
0
        EXPECT_EQ(entry.mSourceType,
311
0
                  dom::RTCRtpSourceEntryType::Synchronization);
312
0
      }
313
0
      if (entry.mSource == csrc0) {
314
0
        csrc0Found = true;
315
0
        EXPECT_EQ(entry.mSourceType,
316
0
                  dom::RTCRtpSourceEntryType::Contributing);
317
0
      }
318
0
      if (entry.mSource == csrc1) {
319
0
        csrc1Found = true;
320
0
        EXPECT_EQ(entry.mSourceType,
321
0
                  dom::RTCRtpSourceEntryType::Contributing);
322
0
      }
323
0
    }
324
0
    EXPECT_TRUE(ssrcFound);
325
0
    EXPECT_TRUE(csrc0Found);
326
0
    EXPECT_TRUE(csrc1Found);
327
0
  }
328
329
  // Observer a header with a CSRC with audio level extension
330
0
  void TestObserveCsrcWithAudioLevel() {
331
0
    RtpSourceObserver observer;
332
0
    webrtc::WebRtcRTPHeader header;
333
0
  }
334
335
};
336
337
0
TEST_F(RtpSourcesTest, TestInitState) { TestInitState(); }
338
0
TEST_F(RtpSourcesTest, TestInsertIntoJitterWindow) {
339
0
  TestInsertIntoJitterWindow();
340
0
}
341
0
TEST_F(RtpSourcesTest, TestAgeIntoLongTerm){ TestAgeIntoLongTerm(); }
342
0
TEST_F(RtpSourcesTest, TestInsertIntoLongTerm) { TestInsertIntoLongTerm(); }
343
0
TEST_F(RtpSourcesTest, TestMaximumAudioLevel) { TestMaximumAudioLevel(); }
344
0
TEST_F(RtpSourcesTest, TestEmptyPrune) { TestEmptyPrune(); }
345
0
TEST_F(RtpSourcesTest, TestSinglePrune) { TestSinglePrune(); }
346
0
TEST_F(RtpSourcesTest, TestKeyManipulation) { TestKeyManipulation(); }
347
0
TEST_F(RtpSourcesTest, TestObserveOneCsrc) { TestObserveOneCsrc(); }
348
0
TEST_F(RtpSourcesTest, TestObserveTwoCsrcs) { TestObserveTwoCsrcs(); }
349
0
TEST_F(RtpSourcesTest, TestObserveCsrcWithAudioLevel) {
350
0
  TestObserveCsrcWithAudioLevel();
351
0
}
352
}