Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: webrtc/call/rtcp_demuxer_unittest.cc

Issue 2943693003: Create RtcpDemuxer (Closed)
Patch Set: . Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <memory>
12
13 #include "webrtc/call/rtcp_demuxer.h"
14
15 #include "webrtc/base/arraysize.h"
16 #include "webrtc/base/checks.h"
17 #include "webrtc/base/ptr_util.h"
18 #include "webrtc/call/rtcp_packet_sink_interface.h"
19 #include "webrtc/common_types.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
21 #include "webrtc/test/gmock.h"
22 #include "webrtc/test/gtest.h"
23
24 namespace webrtc {
25
26 namespace {
27
28 using ::testing::_;
29 using ::testing::AtLeast;
30 using ::testing::ElementsAreArray;
31 using ::testing::InSequence;
32 using ::testing::NiceMock;
33 using ::webrtc::rtcp::RtcpPacket;
danilchap 2017/06/19 16:24:54 used?
eladalon 2017/06/19 19:13:48 Not anymore (I think I was expecting to use this f
34
35 class MockRtcpPacketSink : public RtcpPacketSinkInterface {
36 public:
37 MOCK_METHOD1(OnRtcpPacket, void(rtc::ArrayView<const uint8_t>));
38 };
39
40 // Produces a packet buffer representing an RTCP packet with a given SSRC,
41 // as it would look when sent over the wire.
42 // |distinguishing_string| allows different RTCP packets with the same SSRC
43 // to be distinguished. How this is set into the actual packet is
44 // unimportant, and depends on which RTCP message we choose to use.
45 rtc::Buffer CreateRtcpPacket(uint32_t ssrc,
46 const std::string& distinguishing_string = "") {
47 rtcp::Bye packet;
48 packet.SetSenderSsrc(ssrc);
49 if (distinguishing_string != "") {
danilchap 2017/06/19 16:24:54 why check?
eladalon 2017/06/19 19:13:49 I don't want to assume the implementation of Bye d
50 // Actual way we use |distinguishing_string| is unimportant, so long
51 // as it ends up in the packet.
52 packet.SetReason(distinguishing_string);
53 }
54 return packet.Build();
55 }
56
57 } // namespace
58
59 TEST(RtcpDemuxerTest, OnRtcpPacketCalledOnCorrectSinkBySsrc) {
60 RtcpDemuxer demuxer;
61
62 constexpr uint32_t ssrcs[] = {101, 202, 303};
63 MockRtcpPacketSink sinks[arraysize(ssrcs)];
64 for (size_t i = 0; i < arraysize(ssrcs); i++) {
65 demuxer.AddSink(ssrcs[i], &sinks[i]);
66 }
67
68 for (size_t i = 0; i < arraysize(ssrcs); i++) {
69 auto packet = CreateRtcpPacket(ssrcs[i]);
70 EXPECT_CALL(sinks[i],
71 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())))
72 .Times(1);
73 demuxer.OnRtcpPacket(packet);
74 }
75
76 // Test tear-down
77 for (const auto& sink : sinks) {
78 demuxer.RemoveSink(&sink);
79 }
80 }
81
82 TEST(RtcpDemuxerTest, OnRtcpPacketCalledOnResolvedRsidSink) {
83 RtcpDemuxer demuxer;
84
85 // Set up some RSID sinks.
86 const std::string rsids[] = {"a", "b", "c"};
87 MockRtcpPacketSink sinks[arraysize(rsids)];
88 for (size_t i = 0; i < arraysize(rsids); i++) {
89 demuxer.AddSink(rsids[i], &sinks[i]);
90 }
91
92 // Only resolve one of the sinks.
93 constexpr size_t resolved_sink_index = 0;
94 constexpr uint32_t ssrc = 345;
95 demuxer.OnRsidResolved(rsids[resolved_sink_index], ssrc);
96
97 // The resolved sink gets notifications of RTCP messages with its SSRC.
98 auto packet = CreateRtcpPacket(ssrc);
99 EXPECT_CALL(sinks[resolved_sink_index],
100 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())))
101 .Times(1);
102
103 // RTCP received; expected calls triggered.
104 demuxer.OnRtcpPacket(packet);
105
106 // Test tear-down
107 for (const auto& sink : sinks) {
108 demuxer.RemoveSink(&sink);
109 }
110 }
111
112 TEST(RtcpDemuxerTest,
113 SingleCallbackAfterResolutionOfAnRsidToAlreadyRegisteredSsrc) {
114 RtcpDemuxer demuxer;
115
116 // Associate a sink with an SSRC.
117 MockRtcpPacketSink sink;
118 constexpr uint32_t ssrc = 999;
119 demuxer.AddSink(ssrc, &sink);
120
121 // Associate the same sink with an RSID.
122 const std::string rsid = "r";
123 demuxer.AddSink(rsid, &sink);
124
125 // Resolve the RSID to the aforementioned SSRC.
126 demuxer.OnRsidResolved(rsid, ssrc);
127
128 // OnRtcpPacket still called only a single time for messages with this SSRC.
129 auto packet = CreateRtcpPacket(ssrc);
130 EXPECT_CALL(sink,
131 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())))
132 .Times(1);
133 demuxer.OnRtcpPacket(packet);
134
135 // Test tear-down
136 demuxer.RemoveSink(&sink);
137 }
138
139 TEST(RtcpDemuxerTest, OnRtcpPacketCalledOnAllBroadcastSinksForAllRtcpPackets) {
140 RtcpDemuxer demuxer;
141
142 MockRtcpPacketSink sinks[3];
143 for (MockRtcpPacketSink& sink : sinks) {
144 demuxer.AddBroadcastSink(&sink);
145 }
146
147 constexpr uint32_t ssrc = 747;
148 auto packet = CreateRtcpPacket(ssrc);
149
150 for (MockRtcpPacketSink& sink : sinks) {
151 EXPECT_CALL(sink,
152 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())))
153 .Times(1);
154 }
155
156 // RTCP received; expected calls triggered.
157 demuxer.OnRtcpPacket(packet);
158
159 // Test tear-down
160 for (const auto& sink : sinks) {
161 demuxer.RemoveBroadcastSink(&sink);
162 }
163 }
164
165 TEST(RtcpDemuxerTest, PacketsDeliveredInRightOrderToNonBroadcastSink) {
166 RtcpDemuxer demuxer;
167
168 constexpr uint32_t ssrc = 101;
169 MockRtcpPacketSink sink;
170 demuxer.AddSink(ssrc, &sink);
171
172 std::vector<rtc::Buffer> packets;
173 for (size_t i = 0; i < 5; i++) {
174 packets.emplace_back(CreateRtcpPacket(ssrc, std::to_string(i)));
175 }
176
177 InSequence sequence;
178 for (const auto& packet : packets) {
179 EXPECT_CALL(sink,
180 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())))
181 .Times(1);
182 }
183
184 for (const auto& packet : packets) {
185 demuxer.OnRtcpPacket(packet);
186 }
187
188 // Test tear-down
189 demuxer.RemoveSink(&sink);
190 }
191
192 TEST(RtcpDemuxerTest, PacketsDeliveredInRightOrderToBroadcastSink) {
193 RtcpDemuxer demuxer;
194
195 MockRtcpPacketSink sink;
196 demuxer.AddBroadcastSink(&sink);
197
198 std::vector<rtc::Buffer> packets;
199 for (size_t i = 0; i < 5; i++) {
200 constexpr uint32_t ssrc = 101;
201 packets.emplace_back(CreateRtcpPacket(ssrc, std::to_string(i)));
202 }
203
204 InSequence sequence;
205 for (size_t i = 0; i < 5; i++) {
206 EXPECT_CALL(sink, OnRtcpPacket(ElementsAreArray(packets[i].cbegin(),
207 packets[i].cend())))
208 .Times(1);
209 }
210
211 for (const auto& packet : packets) {
212 demuxer.OnRtcpPacket(packet);
213 }
214
215 // Test tear-down
216 demuxer.RemoveBroadcastSink(&sink);
217 }
218
219 TEST(RtcpDemuxerTest, MultipleSinksMappedToSameSsrc) {
220 RtcpDemuxer demuxer;
221
222 MockRtcpPacketSink sinks[3];
223 constexpr uint32_t ssrc = 404;
224 for (auto& sink : sinks) {
225 demuxer.AddSink(ssrc, &sink);
226 }
227
228 // Reception of an RTCP packet associated with the shared SSRC triggers the
229 // callback on all of the sinks associated with it.
230 auto packet = CreateRtcpPacket(ssrc);
231 for (auto& sink : sinks) {
232 EXPECT_CALL(sink,
233 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())));
234 }
235 demuxer.OnRtcpPacket(packet);
236
237 // Test tear-down
238 for (const auto& sink : sinks) {
239 demuxer.RemoveSink(&sink);
240 }
241 }
242
243 TEST(RtcpDemuxerTest, SinkMappedToMultipleSsrcs) {
244 RtcpDemuxer demuxer;
245
246 constexpr uint32_t ssrcs[] = {404, 505, 606};
247 MockRtcpPacketSink sink;
248 for (uint32_t ssrc : ssrcs) {
249 demuxer.AddSink(ssrc, &sink);
250 }
251
252 // The sink which is associated with multiple SSRCs gets the callback
253 // triggered for each of those SSRCs.
254 for (uint32_t ssrc : ssrcs) {
255 auto packet = CreateRtcpPacket(ssrc);
256 EXPECT_CALL(sink,
257 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())));
258 demuxer.OnRtcpPacket(packet);
259 }
260
261 // Test tear-down
262 demuxer.RemoveSink(&sink);
263 }
264
265 TEST(RtcpDemuxerTest, MultipleRsidsOnSameSink) {
266 RtcpDemuxer demuxer;
267
268 // Sink associated with multiple sinks.
269 MockRtcpPacketSink sink;
270 const std::string rsids[] = {"a", "b", "c"};
271 for (const auto& rsid : rsids) {
272 demuxer.AddSink(rsid, &sink);
273 }
274
275 // RSIDs resolved to SSRCs.
276 uint32_t ssrcs[arraysize(rsids)];
277 for (size_t i = 0; i < arraysize(rsids); i++) {
278 ssrcs[i] = 1000 + static_cast<uint32_t>(i);
279 demuxer.OnRsidResolved(rsids[i], ssrcs[i]);
280 }
281
282 // Set up packets to match those RSIDs/SSRCs.
283 std::vector<rtc::Buffer> packets;
284 for (size_t i = 0; i < arraysize(rsids); i++) {
285 packets.emplace_back(CreateRtcpPacket(ssrcs[i]));
danilchap 2017/06/19 16:24:55 why emplace_back instead of push_back? (packets::v
eladalon 2017/06/19 19:13:49 The two should behave the same in this case, but I
286 }
287
288 // The sink expects to receive all of the packets.
289 for (const auto& packet : packets) {
290 EXPECT_CALL(sink,
291 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())))
292 .Times(1);
293 }
294
295 // Packet demuxed correctly; OnRtcpPacket() triggered on sink.
296 for (const auto& packet : packets) {
297 demuxer.OnRtcpPacket(packet);
298 }
299
300 // Test tear-down
301 demuxer.RemoveSink(&sink);
302 }
303
304 TEST(RtcpDemuxerTest, RsidUsedByMultipleSinks) {
305 RtcpDemuxer demuxer;
306
307 MockRtcpPacketSink sinks[3];
308 const std::string shared_rsid = "a";
309
310 for (MockRtcpPacketSink& sink : sinks) {
311 demuxer.AddSink(shared_rsid, &sink);
312 }
313
314 constexpr uint32_t shared_ssrc = 888;
315 demuxer.OnRsidResolved(shared_rsid, shared_ssrc);
316
317 auto packet = CreateRtcpPacket(shared_ssrc);
318
319 for (MockRtcpPacketSink& sink : sinks) {
320 EXPECT_CALL(sink,
321 OnRtcpPacket(ElementsAreArray(packet.cbegin(), packet.cend())))
322 .Times(1);
323 }
324
325 demuxer.OnRtcpPacket(packet);
326
327 // Test tear-down
328 for (MockRtcpPacketSink& sink : sinks) {
329 demuxer.RemoveSink(&sink);
330 }
331 }
332
333 TEST(RtcpDemuxerTest, NoCallbackOnSsrcSinkRemovedBeforeFirstPacket) {
334 RtcpDemuxer demuxer;
335
336 constexpr uint32_t ssrc = 404;
337 MockRtcpPacketSink sink;
338 demuxer.AddSink(ssrc, &sink);
339
340 demuxer.RemoveSink(&sink);
341
342 // The removed sink does not get callbacks.
343 auto packet = CreateRtcpPacket(ssrc);
344 EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
danilchap 2017/06/19 16:24:54 may be remove the comment - it just repeats '.Time
eladalon 2017/06/19 19:13:48 Feels slightly clearer to me. Times(0) seems a bit
345 demuxer.OnRtcpPacket(packet);
346 }
347
348 TEST(RtcpDemuxerTest, NoCallbackOnSsrcSinkRemovedAfterFirstPacket) {
349 RtcpDemuxer demuxer;
350
351 constexpr uint32_t ssrc = 404;
352 NiceMock<MockRtcpPacketSink> sink;
353 demuxer.AddSink(ssrc, &sink);
354
355 auto before_packet = CreateRtcpPacket(ssrc);
356 demuxer.OnRtcpPacket(before_packet);
357
358 demuxer.RemoveSink(&sink);
359
360 // The removed sink does not get callbacks.
361 auto after_packet = CreateRtcpPacket(ssrc);
362 EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
363 demuxer.OnRtcpPacket(after_packet);
364 }
365
366 TEST(RtcpDemuxerTest, NoCallbackOnRsidSinkRemovedBeforeRsidResolution) {
367 RtcpDemuxer demuxer;
368
369 const std::string rsid = "a";
370 constexpr uint32_t ssrc = 404;
371 MockRtcpPacketSink sink;
372 demuxer.AddSink(rsid, &sink);
373
374 // Removal before resolution.
375 demuxer.RemoveSink(&sink);
376 demuxer.OnRsidResolved(rsid, ssrc);
377
378 // The removed sink does not get callbacks.
379 auto packet = CreateRtcpPacket(ssrc);
380 EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
381 demuxer.OnRtcpPacket(packet);
382 }
383
384 TEST(RtcpDemuxerTest, NoCallbackOnRsidSinkRemovedAfterRsidResolution) {
385 RtcpDemuxer demuxer;
386
387 const std::string rsid = "a";
388 constexpr uint32_t ssrc = 404;
389 MockRtcpPacketSink sink;
390 demuxer.AddSink(rsid, &sink);
391
392 // Removal after resolution.
393 demuxer.OnRsidResolved(rsid, ssrc);
394 demuxer.RemoveSink(&sink);
395
396 // The removed sink does not get callbacks.
397 auto packet = CreateRtcpPacket(ssrc);
398 EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
399 demuxer.OnRtcpPacket(packet);
400 }
401
402 TEST(RtcpDemuxerTest, NoCallbackOnBroadcastSinkRemovedBeforeFirstPacket) {
403 RtcpDemuxer demuxer;
404
405 MockRtcpPacketSink sink;
406 demuxer.AddBroadcastSink(&sink);
407
408 demuxer.RemoveBroadcastSink(&sink);
409
410 // The removed sink does not get callbacks.
411 constexpr uint32_t ssrc = 404;
412 auto packet = CreateRtcpPacket(ssrc);
413 EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
414 demuxer.OnRtcpPacket(packet);
415 }
416
417 TEST(RtcpDemuxerTest, NoCallbackOnBroadcastSinkRemovedAfterFirstPacket) {
418 RtcpDemuxer demuxer;
419
420 NiceMock<MockRtcpPacketSink> sink;
421 demuxer.AddBroadcastSink(&sink);
422
423 constexpr uint32_t ssrc = 404;
424 auto before_packet = CreateRtcpPacket(ssrc);
425 demuxer.OnRtcpPacket(before_packet);
426
427 demuxer.RemoveBroadcastSink(&sink);
428
429 // The removed sink does not get callbacks.
430 auto after_packet = CreateRtcpPacket(ssrc);
431 EXPECT_CALL(sink, OnRtcpPacket(_)).Times(0); // Not called.
432 demuxer.OnRtcpPacket(after_packet);
433 }
434
435 // The RSID to SSRC mapping should be one-to-one. If we end up receiving
436 // two (or more) packets with the same SSRC, but different RSIDs, we guarantee
437 // remembering the first one; no guarantees are made about further associations.
438 TEST(RtcpDemuxerTest, FirstRsolutionOfRsidNotForgotten) {
439 RtcpDemuxer demuxer;
440 MockRtcpPacketSink sink;
441
442 const std::string rsid = "a";
443 demuxer.AddSink(rsid, &sink);
444
445 constexpr uint32_t ssrc_a = 111; // First resolution - guaranteed effective.
446 demuxer.OnRsidResolved(rsid, ssrc_a);
447
448 constexpr uint32_t ssrc_b = 222; // Second resolution - no guarantees.
449 demuxer.OnRsidResolved(rsid, ssrc_b);
450
451 auto packet_a = CreateRtcpPacket(ssrc_a);
452 EXPECT_CALL(
453 sink, OnRtcpPacket(ElementsAreArray(packet_a.cbegin(), packet_a.cend())))
454 .Times(1);
455 demuxer.OnRtcpPacket(packet_a);
456
457 auto packet_b = CreateRtcpPacket(ssrc_b);
458 EXPECT_CALL(
459 sink, OnRtcpPacket(ElementsAreArray(packet_b.cbegin(), packet_b.cend())))
460 .Times(AtLeast(0));
461 demuxer.OnRtcpPacket(packet_b);
462
463 // Test tear-down
464 demuxer.RemoveSink(&sink);
465 }
466
467 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
468 TEST(RtcpDemuxerTest, RepeatedSsrcToSinkAssociationsDisallowed) {
469 RtcpDemuxer demuxer;
470 MockRtcpPacketSink sink;
471
472 constexpr uint32_t ssrc = 101;
473 demuxer.AddSink(ssrc, &sink);
474 EXPECT_DEATH(demuxer.AddSink(ssrc, &sink), "");
475
476 // Test tear-down
477 demuxer.RemoveSink(&sink);
478 }
479
480 TEST(RtcpDemuxerTest, RepeatedRsidToSinkAssociationsDisallowed) {
481 RtcpDemuxer demuxer;
482 MockRtcpPacketSink sink;
483
484 const std::string rsid = "z";
485 demuxer.AddSink(rsid, &sink);
486 EXPECT_DEATH(demuxer.AddSink(rsid, &sink), "");
487
488 // Test tear-down
489 demuxer.RemoveSink(&sink);
490 }
491
492 TEST(RtcpDemuxerTest, RepeatedBroadcastSinkRegistrationDisallowed) {
493 RtcpDemuxer demuxer;
494 MockRtcpPacketSink sink;
495
496 demuxer.AddBroadcastSink(&sink);
497 EXPECT_DEATH(demuxer.AddBroadcastSink(&sink), "");
498
499 // Test tear-down
500 demuxer.RemoveBroadcastSink(&sink);
501 }
502
503 TEST(RtcpDemuxerTest, SsrcSinkCannotAlsoBeRegisteredAsBroadcast) {
504 RtcpDemuxer demuxer;
505 MockRtcpPacketSink sink;
506
507 constexpr uint32_t ssrc = 101;
508 demuxer.AddSink(ssrc, &sink);
509 EXPECT_DEATH(demuxer.AddBroadcastSink(&sink), "");
510
511 // Test tear-down
512 demuxer.RemoveSink(&sink);
513 }
514
515 TEST(RtcpDemuxerTest, RsidSinkCannotAlsoBeRegisteredAsBroadcast) {
516 RtcpDemuxer demuxer;
517 MockRtcpPacketSink sink;
518
519 const std::string rsid = "z";
520 demuxer.AddSink(rsid, &sink);
521 EXPECT_DEATH(demuxer.AddBroadcastSink(&sink), "");
522
523 // Test tear-down
524 demuxer.RemoveSink(&sink);
525 }
526
527 TEST(RtcpDemuxerTest, BroadcastSinkCannotAlsoBeRegisteredAsSsrcSink) {
528 RtcpDemuxer demuxer;
529 MockRtcpPacketSink sink;
530
531 demuxer.AddBroadcastSink(&sink);
532 constexpr uint32_t ssrc = 101;
533 EXPECT_DEATH(demuxer.AddSink(ssrc, &sink), "");
534
535 // Test tear-down
536 demuxer.RemoveBroadcastSink(&sink);
537 }
538
539 TEST(RtcpDemuxerTest, BroadcastSinkCannotAlsoBeRegisteredAsRsidSink) {
540 RtcpDemuxer demuxer;
541 MockRtcpPacketSink sink;
542
543 demuxer.AddBroadcastSink(&sink);
544 const std::string rsid = "j";
545 EXPECT_DEATH(demuxer.AddSink(rsid, &sink), "");
546
547 // Test tear-down
548 demuxer.RemoveBroadcastSink(&sink);
549 }
550
551 TEST(RtcpDemuxerTest, MayNotCallRemoveSinkOnNeverAddedSink) {
552 RtcpDemuxer demuxer;
553 MockRtcpPacketSink sink;
554
555 EXPECT_DEATH(demuxer.RemoveSink(&sink), "");
556 }
557
558 TEST(RtcpDemuxerTest, MayNotCallRemoveBroadcastSinkOnNeverAddedSink) {
559 RtcpDemuxer demuxer;
560 MockRtcpPacketSink sink;
561
562 EXPECT_DEATH(demuxer.RemoveBroadcastSink(&sink), "");
563 }
564
565 TEST(RtcpDemuxerTest, RsidMustBeNonEmpty) {
566 RtcpDemuxer demuxer;
567 MockRtcpPacketSink sink;
568 EXPECT_DEATH(demuxer.AddSink("", &sink), "");
569 }
570
571 TEST(RtcpDemuxerTest, RsidMustBeAlphaNumeric) {
572 RtcpDemuxer demuxer;
573 MockRtcpPacketSink sink;
574 EXPECT_DEATH(demuxer.AddSink("a_3", &sink), "");
575 }
576
577 TEST(RtcpDemuxerTest, RsidMustNotExceedMaximumLength) {
578 RtcpDemuxer demuxer;
579 MockRtcpPacketSink sink;
580 std::string rsid(StreamId::kMaxSize + 1, 'a');
581 EXPECT_DEATH(demuxer.AddSink(rsid, &sink), "");
582 }
583 #endif
584 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698