1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h"
6
7 #include "base/run_loop.h"
8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom-blink.h"
11 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
12 #include "third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h"
13 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h"
14 #include "third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_client.h"
15 #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h"
16 #include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
17 #include "third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h"
18 #include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_receiver_platform.h"
19 #include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_sender_platform.h"
20 #include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h"
21
22 using ::testing::_;
23
24 namespace blink {
25
26 const char* kDefaultTransceiverString =
27 "getTransceivers()[0]:{\n"
28 " mid:null,\n"
29 " sender:{\n"
30 " track:'senderTrackId',\n"
31 " streams:['senderStreamId'],\n"
32 " },\n"
33 " receiver:{\n"
34 " track:'receiverTrackId',\n"
35 " streams:['receiverStreamId'],\n"
36 " },\n"
37 " stopped:false,\n"
38 " direction:'sendonly',\n"
39 " currentDirection:null,\n"
40 "}";
41
42 const char* kDefaultSenderString =
43 "getSenders()[0]:{\n"
44 " track:'senderTrackId',\n"
45 " streams:['senderStreamId'],\n"
46 "}";
47
48 const char* kDefaultReceiverString =
49 "getReceivers()[0]:{\n"
50 " track:'receiverTrackId',\n"
51 " streams:['receiverStreamId'],\n"
52 "}";
53
54 class MockPeerConnectionTrackerHost
55 : public blink::mojom::blink::PeerConnectionTrackerHost {
56 public:
MockPeerConnectionTrackerHost()57 MockPeerConnectionTrackerHost() {}
58 MOCK_METHOD3(UpdatePeerConnection, void(int, const String&, const String&));
59 MOCK_METHOD1(AddPeerConnection,
60 void(blink::mojom::blink::PeerConnectionInfoPtr));
61 MOCK_METHOD1(RemovePeerConnection, void(int));
62 MOCK_METHOD2(OnPeerConnectionSessionIdSet, void(int, const String&));
63 MOCK_METHOD5(GetUserMedia,
64 void(const String&, bool, bool, const String&, const String&));
65 MOCK_METHOD2(WebRtcEventLogWrite, void(int, const Vector<uint8_t>&));
66 MOCK_METHOD2(AddStandardStats, void(int, base::Value));
67 MOCK_METHOD2(AddLegacyStats, void(int, base::Value));
68
69 mojo::Remote<blink::mojom::blink::PeerConnectionTrackerHost>
CreatePendingRemoteAndBind()70 CreatePendingRemoteAndBind() {
71 receiver_.reset();
72 return mojo::Remote<blink::mojom::blink::PeerConnectionTrackerHost>(
73 receiver_.BindNewPipeAndPassRemote(
74 blink::scheduler::GetSingleThreadTaskRunnerForTesting()));
75 }
76
77 mojo::Receiver<blink::mojom::blink::PeerConnectionTrackerHost> receiver_{
78 this};
79 };
80
81 // Creates a transceiver that is expected to be logged as
82 // |kDefaultTransceiverString|, |kDefaultSenderString| or
83 // |kDefaultReceiverString| depending on if |implementation_type| refers to a
84 // fully implemented, sender-only or receiver-only transceiver.
85 //
86 // This is used in unittests that don't care about the specific attributes of
87 // the transceiver.
CreateDefaultTransceiver(RTCRtpTransceiverPlatformImplementationType implementation_type)88 std::unique_ptr<RTCRtpTransceiverPlatform> CreateDefaultTransceiver(
89 RTCRtpTransceiverPlatformImplementationType implementation_type) {
90 std::unique_ptr<RTCRtpTransceiverPlatform> transceiver;
91 blink::FakeRTCRtpSenderImpl sender(
92 "senderTrackId", {"senderStreamId"},
93 blink::scheduler::GetSingleThreadTaskRunnerForTesting());
94 blink::FakeRTCRtpReceiverImpl receiver(
95 "receiverTrackId", {"receiverStreamId"},
96 blink::scheduler::GetSingleThreadTaskRunnerForTesting());
97 if (implementation_type ==
98 RTCRtpTransceiverPlatformImplementationType::kFullTransceiver) {
99 transceiver = std::make_unique<blink::FakeRTCRtpTransceiverImpl>(
100 base::nullopt, std::move(sender), std::move(receiver),
101 false /* stopped */,
102 webrtc::RtpTransceiverDirection::kSendOnly /* direction */,
103 base::nullopt /* current_direction */);
104 } else if (implementation_type ==
105 RTCRtpTransceiverPlatformImplementationType::kPlanBSenderOnly) {
106 transceiver = std::make_unique<blink::RTCRtpSenderOnlyTransceiver>(
107 std::make_unique<blink::FakeRTCRtpSenderImpl>(sender));
108 } else {
109 DCHECK_EQ(implementation_type,
110 RTCRtpTransceiverPlatformImplementationType::kPlanBReceiverOnly);
111 transceiver = std::make_unique<blink::RTCRtpReceiverOnlyTransceiver>(
112 std::make_unique<blink::FakeRTCRtpReceiverImpl>(receiver));
113 }
114 return transceiver;
115 }
116
117 namespace {
118
119 // TODO(https://crbug.com/868868): Move this into a separate file.
120 class MockPeerConnectionHandler : public RTCPeerConnectionHandler {
121 public:
MockPeerConnectionHandler()122 MockPeerConnectionHandler()
123 : RTCPeerConnectionHandler(
124 &client_,
125 &dependency_factory_,
126 blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
127 /*force_encoded_audio_insertable_streams=*/false,
128 /*force_encoded_video_insertable_streams=*/false) {}
129 MOCK_METHOD0(CloseClientPeerConnection, void());
130
131 private:
132 blink::MockPeerConnectionDependencyFactory dependency_factory_;
133 MockRTCPeerConnectionHandlerClient client_;
134 };
135
136 } // namespace
137
138 class PeerConnectionTrackerTest : public ::testing::Test {
139 public:
CreateTrackerWithMocks()140 void CreateTrackerWithMocks() {
141 mock_host_.reset(new MockPeerConnectionTrackerHost());
142 tracker_.reset(new PeerConnectionTracker(
143 mock_host_->CreatePendingRemoteAndBind(),
144 blink::scheduler::GetSingleThreadTaskRunnerForTesting()));
145 }
146
CreateAndRegisterPeerConnectionHandler()147 void CreateAndRegisterPeerConnectionHandler() {
148 mock_handler_.reset(new MockPeerConnectionHandler());
149 EXPECT_CALL(*mock_host_, AddPeerConnection(_));
150 tracker_->RegisterPeerConnection(
151 mock_handler_.get(),
152 webrtc::PeerConnectionInterface::RTCConfiguration(), MediaConstraints(),
153 nullptr);
154 base::RunLoop().RunUntilIdle();
155 }
156
157 protected:
158 std::unique_ptr<MockPeerConnectionTrackerHost> mock_host_;
159 std::unique_ptr<PeerConnectionTracker> tracker_;
160 std::unique_ptr<MockPeerConnectionHandler> mock_handler_;
161 };
162
TEST_F(PeerConnectionTrackerTest,CreatingObject)163 TEST_F(PeerConnectionTrackerTest, CreatingObject) {
164 PeerConnectionTracker tracker(
165 blink::scheduler::GetSingleThreadTaskRunnerForTesting());
166 }
167
TEST_F(PeerConnectionTrackerTest,TrackCreateOffer)168 TEST_F(PeerConnectionTrackerTest, TrackCreateOffer) {
169 CreateTrackerWithMocks();
170 CreateAndRegisterPeerConnectionHandler();
171 // Note: blink::RTCOfferOptionsPlatform is not mockable. So we can't write
172 // tests for anything but a null options parameter.
173 RTCOfferOptionsPlatform* options =
174 MakeGarbageCollected<RTCOfferOptionsPlatform>(0, 0, false, false);
175 EXPECT_CALL(
176 *mock_host_,
177 UpdatePeerConnection(
178 _, String("createOffer"),
179 String("options: {offerToReceiveVideo: 0, offerToReceiveAudio: 0, "
180 "voiceActivityDetection: false, iceRestart: false}")));
181 tracker_->TrackCreateOffer(mock_handler_.get(), options);
182 base::RunLoop().RunUntilIdle();
183 }
184
TEST_F(PeerConnectionTrackerTest,OnSuspend)185 TEST_F(PeerConnectionTrackerTest, OnSuspend) {
186 CreateTrackerWithMocks();
187 CreateAndRegisterPeerConnectionHandler();
188 EXPECT_CALL(*mock_handler_, CloseClientPeerConnection());
189 tracker_->OnSuspend();
190 }
191
TEST_F(PeerConnectionTrackerTest,AddTransceiverWithOptionalValuesPresent)192 TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesPresent) {
193 CreateTrackerWithMocks();
194 CreateAndRegisterPeerConnectionHandler();
195 blink::FakeRTCRtpTransceiverImpl transceiver(
196 "midValue",
197 blink::FakeRTCRtpSenderImpl(
198 "senderTrackId", {"streamIdA", "streamIdB"},
199 blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
200 blink::FakeRTCRtpReceiverImpl(
201 "receiverTrackId", {"streamIdC"},
202 blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
203 true /* stopped */,
204 webrtc::RtpTransceiverDirection::kSendRecv /* direction */,
205 webrtc::RtpTransceiverDirection::kInactive /* current_direction */);
206 String update_value;
207 EXPECT_CALL(*mock_host_,
208 UpdatePeerConnection(_, String("transceiverAdded"), _))
209 .WillOnce(testing::SaveArg<2>(&update_value));
210 tracker_->TrackAddTransceiver(
211 mock_handler_.get(),
212 PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, transceiver,
213 0u);
214 base::RunLoop().RunUntilIdle();
215 String expected_value(
216 "Caused by: addTrack\n"
217 "\n"
218 "getTransceivers()[0]:{\n"
219 " mid:'midValue',\n"
220 " sender:{\n"
221 " track:'senderTrackId',\n"
222 " streams:['streamIdA','streamIdB'],\n"
223 " },\n"
224 " receiver:{\n"
225 " track:'receiverTrackId',\n"
226 " streams:['streamIdC'],\n"
227 " },\n"
228 " stopped:true,\n"
229 " direction:'sendrecv',\n"
230 " currentDirection:'inactive',\n"
231 "}");
232 EXPECT_EQ(expected_value, update_value);
233 }
234
TEST_F(PeerConnectionTrackerTest,AddTransceiverWithOptionalValuesNull)235 TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesNull) {
236 CreateTrackerWithMocks();
237 CreateAndRegisterPeerConnectionHandler();
238 blink::FakeRTCRtpTransceiverImpl transceiver(
239 base::nullopt,
240 blink::FakeRTCRtpSenderImpl(
241 base::nullopt, {},
242 blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
243 blink::FakeRTCRtpReceiverImpl(
244 "receiverTrackId", {},
245 blink::scheduler::GetSingleThreadTaskRunnerForTesting()),
246 false /* stopped */,
247 webrtc::RtpTransceiverDirection::kInactive /* direction */,
248 base::nullopt /* current_direction */);
249 String update_value;
250 EXPECT_CALL(*mock_host_,
251 UpdatePeerConnection(_, String("transceiverAdded"), _))
252 .WillOnce(testing::SaveArg<2>(&update_value));
253 tracker_->TrackAddTransceiver(
254 mock_handler_.get(),
255 PeerConnectionTracker::TransceiverUpdatedReason::kAddTransceiver,
256 transceiver, 1u);
257 base::RunLoop().RunUntilIdle();
258 String expected_value(
259 "Caused by: addTransceiver\n"
260 "\n"
261 "getTransceivers()[1]:{\n"
262 " mid:null,\n"
263 " sender:{\n"
264 " track:null,\n"
265 " streams:[],\n"
266 " },\n"
267 " receiver:{\n"
268 " track:'receiverTrackId',\n"
269 " streams:[],\n"
270 " },\n"
271 " stopped:false,\n"
272 " direction:'inactive',\n"
273 " currentDirection:null,\n"
274 "}");
275 EXPECT_EQ(expected_value, update_value);
276 }
277
TEST_F(PeerConnectionTrackerTest,ModifyTransceiver)278 TEST_F(PeerConnectionTrackerTest, ModifyTransceiver) {
279 CreateTrackerWithMocks();
280 CreateAndRegisterPeerConnectionHandler();
281 auto transceiver = CreateDefaultTransceiver(
282 RTCRtpTransceiverPlatformImplementationType::kFullTransceiver);
283 String update_value;
284 EXPECT_CALL(*mock_host_,
285 UpdatePeerConnection(_, String("transceiverModified"), _))
286 .WillOnce(testing::SaveArg<2>(&update_value));
287 tracker_->TrackModifyTransceiver(
288 mock_handler_.get(),
289 PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription,
290 *transceiver, 0u);
291 base::RunLoop().RunUntilIdle();
292 String expected_value("Caused by: setLocalDescription\n\n" +
293 String(kDefaultTransceiverString));
294 EXPECT_EQ(expected_value, update_value);
295 }
296
TEST_F(PeerConnectionTrackerTest,RemoveTransceiver)297 TEST_F(PeerConnectionTrackerTest, RemoveTransceiver) {
298 CreateTrackerWithMocks();
299 CreateAndRegisterPeerConnectionHandler();
300 auto transceiver = CreateDefaultTransceiver(
301 RTCRtpTransceiverPlatformImplementationType::kFullTransceiver);
302 String update_value;
303 EXPECT_CALL(*mock_host_,
304 UpdatePeerConnection(_, String("transceiverRemoved"), _))
305 .WillOnce(testing::SaveArg<2>(&update_value));
306 tracker_->TrackRemoveTransceiver(
307 mock_handler_.get(),
308 PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack,
309 *transceiver, 0u);
310 base::RunLoop().RunUntilIdle();
311 String expected_value(
312 "Caused by: removeTrack\n"
313 "\n" +
314 String(kDefaultTransceiverString));
315 EXPECT_EQ(expected_value, update_value);
316 }
317
TEST_F(PeerConnectionTrackerTest,AddSender)318 TEST_F(PeerConnectionTrackerTest, AddSender) {
319 CreateTrackerWithMocks();
320 CreateAndRegisterPeerConnectionHandler();
321 auto sender_only = CreateDefaultTransceiver(
322 RTCRtpTransceiverPlatformImplementationType::kPlanBSenderOnly);
323 String update_value;
324 EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, String("senderAdded"), _))
325 .WillOnce(testing::SaveArg<2>(&update_value));
326 tracker_->TrackAddTransceiver(
327 mock_handler_.get(),
328 PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription,
329 *sender_only, 0u);
330 base::RunLoop().RunUntilIdle();
331 String expected_value(
332 "Caused by: setLocalDescription\n"
333 "\n" +
334 String(kDefaultSenderString));
335 EXPECT_EQ(expected_value, update_value);
336 }
337
TEST_F(PeerConnectionTrackerTest,ModifySender)338 TEST_F(PeerConnectionTrackerTest, ModifySender) {
339 CreateTrackerWithMocks();
340 CreateAndRegisterPeerConnectionHandler();
341 auto sender_only = CreateDefaultTransceiver(
342 RTCRtpTransceiverPlatformImplementationType::kPlanBSenderOnly);
343 String update_value;
344 EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, String("senderModified"), _))
345 .WillOnce(testing::SaveArg<2>(&update_value));
346 tracker_->TrackModifyTransceiver(
347 mock_handler_.get(),
348 PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
349 *sender_only, 0u);
350 base::RunLoop().RunUntilIdle();
351 String expected_value(
352 "Caused by: setRemoteDescription\n"
353 "\n" +
354 String(kDefaultSenderString));
355 EXPECT_EQ(expected_value, update_value);
356 }
357
TEST_F(PeerConnectionTrackerTest,RemoveSender)358 TEST_F(PeerConnectionTrackerTest, RemoveSender) {
359 CreateTrackerWithMocks();
360 CreateAndRegisterPeerConnectionHandler();
361 auto sender_only = CreateDefaultTransceiver(
362 RTCRtpTransceiverPlatformImplementationType::kPlanBSenderOnly);
363 String update_value;
364 EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, String("senderRemoved"), _))
365 .WillOnce(testing::SaveArg<2>(&update_value));
366 tracker_->TrackRemoveTransceiver(
367 mock_handler_.get(),
368 PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
369 *sender_only, 0u);
370 base::RunLoop().RunUntilIdle();
371 String expected_value(
372 "Caused by: setRemoteDescription\n"
373 "\n" +
374 String(kDefaultSenderString));
375 EXPECT_EQ(expected_value, update_value);
376 }
377
TEST_F(PeerConnectionTrackerTest,AddReceiver)378 TEST_F(PeerConnectionTrackerTest, AddReceiver) {
379 CreateTrackerWithMocks();
380 CreateAndRegisterPeerConnectionHandler();
381 auto receiver_only = CreateDefaultTransceiver(
382 RTCRtpTransceiverPlatformImplementationType::kPlanBReceiverOnly);
383 String update_value;
384 EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, String("receiverAdded"), _))
385 .WillOnce(testing::SaveArg<2>(&update_value));
386 tracker_->TrackAddTransceiver(
387 mock_handler_.get(),
388 PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
389 *receiver_only, 0u);
390 base::RunLoop().RunUntilIdle();
391 String expected_value(
392 "Caused by: setRemoteDescription\n"
393 "\n" +
394 String(kDefaultReceiverString));
395 EXPECT_EQ(expected_value, update_value);
396 }
397
TEST_F(PeerConnectionTrackerTest,ModifyReceiver)398 TEST_F(PeerConnectionTrackerTest, ModifyReceiver) {
399 CreateTrackerWithMocks();
400 CreateAndRegisterPeerConnectionHandler();
401 auto receiver_only = CreateDefaultTransceiver(
402 RTCRtpTransceiverPlatformImplementationType::kPlanBReceiverOnly);
403 String update_value;
404 EXPECT_CALL(*mock_host_,
405 UpdatePeerConnection(_, String("receiverModified"), _))
406 .WillOnce(testing::SaveArg<2>(&update_value));
407 tracker_->TrackModifyTransceiver(
408 mock_handler_.get(),
409 PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
410 *receiver_only, 0u);
411 base::RunLoop().RunUntilIdle();
412 String expected_value(
413 "Caused by: setRemoteDescription\n"
414 "\n" +
415 String(kDefaultReceiverString));
416 EXPECT_EQ(expected_value, update_value);
417 }
418
TEST_F(PeerConnectionTrackerTest,RemoveReceiver)419 TEST_F(PeerConnectionTrackerTest, RemoveReceiver) {
420 CreateTrackerWithMocks();
421 CreateAndRegisterPeerConnectionHandler();
422 auto receiver_only = CreateDefaultTransceiver(
423 RTCRtpTransceiverPlatformImplementationType::kPlanBReceiverOnly);
424 String update_value;
425 EXPECT_CALL(*mock_host_,
426 UpdatePeerConnection(_, String("receiverRemoved"), _))
427 .WillOnce(testing::SaveArg<2>(&update_value));
428 tracker_->TrackRemoveTransceiver(
429 mock_handler_.get(),
430 PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription,
431 *receiver_only, 0u);
432 base::RunLoop().RunUntilIdle();
433 String expected_value(
434 "Caused by: setRemoteDescription\n"
435 "\n" +
436 String(kDefaultReceiverString));
437 EXPECT_EQ(expected_value, update_value);
438 }
439
TEST_F(PeerConnectionTrackerTest,IceCandidateError)440 TEST_F(PeerConnectionTrackerTest, IceCandidateError) {
441 CreateTrackerWithMocks();
442 CreateAndRegisterPeerConnectionHandler();
443 auto receiver_only = CreateDefaultTransceiver(
444 RTCRtpTransceiverPlatformImplementationType::kPlanBReceiverOnly);
445 String update_value;
446 EXPECT_CALL(*mock_host_,
447 UpdatePeerConnection(_, String("icecandidateerror"), _))
448 .WillOnce(testing::SaveArg<2>(&update_value));
449 tracker_->TrackIceCandidateError(mock_handler_.get(), "1.1.1.1", 15, "[::1]",
450 "test url", 404, "test error");
451 base::RunLoop().RunUntilIdle();
452 String expected_value(
453 "url: test url\n"
454 "address: 1.1.1.1\n"
455 "port: 15\n"
456 "host_candidate: [::1]\n"
457 "error_text: test error\n"
458 "error_code: 404");
459 EXPECT_EQ(expected_value, update_value);
460 }
461
462 // TODO(hta): Write tests for the other tracking functions.
463
464 } // namespace blink
465