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