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

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

Powered by Google App Engine
This is Rietveld 408576698