/* * Copyright 2017 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include "media/base/fakemediaengine.h" #include "ortc/ortcfactory.h" #include "ortc/testrtpparameters.h" #include "p2p/base/fakepackettransport.h" #include "rtc_base/fakenetwork.h" #include "rtc_base/gunit.h" #include "rtc_base/virtualsocketserver.h" namespace webrtc { // This test uses a virtual network and fake media engine, in order to test the // OrtcFactory at only an API level. Any end-to-end test should go in // ortcfactory_integrationtest.cc instead. class OrtcFactoryTest : public testing::Test { public: OrtcFactoryTest() : thread_(&virtual_socket_server_), fake_packet_transport_("fake transport") { ortc_factory_ = OrtcFactory::Create(&thread_, nullptr, &fake_network_manager_, nullptr, nullptr, std::unique_ptr( new cricket::FakeMediaEngine())) .MoveValue(); } protected: // Uses a single pre-made FakePacketTransport, so shouldn't be called twice in // the same test. std::unique_ptr CreateRtpTransportWithFakePacketTransport() { return ortc_factory_ ->CreateRtpTransport(MakeRtcpMuxParameters(), &fake_packet_transport_, nullptr, nullptr) .MoveValue(); } rtc::VirtualSocketServer virtual_socket_server_; rtc::AutoSocketServerThread thread_; rtc::FakeNetworkManager fake_network_manager_; rtc::FakePacketTransport fake_packet_transport_; std::unique_ptr ortc_factory_; }; TEST_F(OrtcFactoryTest, CanCreateMultipleRtpTransportControllers) { auto controller_result1 = ortc_factory_->CreateRtpTransportController(); EXPECT_TRUE(controller_result1.ok()); auto controller_result2 = ortc_factory_->CreateRtpTransportController(); EXPECT_TRUE(controller_result1.ok()); } // Simple test for the successful cases of CreateRtpTransport. TEST_F(OrtcFactoryTest, CreateRtpTransportWithAndWithoutMux) { rtc::FakePacketTransport rtp("rtp"); rtc::FakePacketTransport rtcp("rtcp"); // With muxed RTCP. RtpTransportParameters parameters = MakeRtcpMuxParameters(); auto result = ortc_factory_->CreateRtpTransport(parameters, &rtp, nullptr, nullptr); EXPECT_TRUE(result.ok()); result.MoveValue().reset(); // With non-muxed RTCP. parameters.rtcp.mux = false; result = ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr); EXPECT_TRUE(result.ok()); } // Simple test for the successful cases of CreateSrtpTransport. TEST_F(OrtcFactoryTest, CreateSrtpTransport) { rtc::FakePacketTransport rtp("rtp"); rtc::FakePacketTransport rtcp("rtcp"); // With muxed RTCP. RtpTransportParameters parameters = MakeRtcpMuxParameters(); auto result = ortc_factory_->CreateSrtpTransport(parameters, &rtp, nullptr, nullptr); EXPECT_TRUE(result.ok()); result.MoveValue().reset(); // With non-muxed RTCP. parameters.rtcp.mux = false; result = ortc_factory_->CreateSrtpTransport(parameters, &rtp, &rtcp, nullptr); EXPECT_TRUE(result.ok()); } // If no CNAME is provided, one should be generated and returned by // GetRtpParameters. TEST_F(OrtcFactoryTest, CreateRtpTransportGeneratesCname) { rtc::FakePacketTransport rtp("rtp"); auto result = ortc_factory_->CreateRtpTransport(MakeRtcpMuxParameters(), &rtp, nullptr, nullptr); ASSERT_TRUE(result.ok()); EXPECT_FALSE(result.value()->GetParameters().rtcp.cname.empty()); } // Extension of the above test; multiple transports created by the same factory // should use the same generated CNAME. TEST_F(OrtcFactoryTest, MultipleRtpTransportsUseSameGeneratedCname) { rtc::FakePacketTransport packet_transport1("1"); rtc::FakePacketTransport packet_transport2("2"); RtpTransportParameters parameters = MakeRtcpMuxParameters(); // Sanity check. ASSERT_TRUE(parameters.rtcp.cname.empty()); auto result = ortc_factory_->CreateRtpTransport( parameters, &packet_transport1, nullptr, nullptr); ASSERT_TRUE(result.ok()); auto rtp_transport1 = result.MoveValue(); result = ortc_factory_->CreateRtpTransport(parameters, &packet_transport2, nullptr, nullptr); ASSERT_TRUE(result.ok()); auto rtp_transport2 = result.MoveValue(); RtcpParameters params1 = rtp_transport1->GetParameters().rtcp; RtcpParameters params2 = rtp_transport2->GetParameters().rtcp; EXPECT_FALSE(params1.cname.empty()); EXPECT_EQ(params1.cname, params2.cname); } TEST_F(OrtcFactoryTest, CreateRtpTransportWithNoPacketTransport) { auto result = ortc_factory_->CreateRtpTransport(MakeRtcpMuxParameters(), nullptr, nullptr, nullptr); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); } // If the |mux| member of the RtcpParameters is false, both an RTP and RTCP // packet transport are needed. TEST_F(OrtcFactoryTest, CreateRtpTransportWithMissingRtcpTransport) { rtc::FakePacketTransport rtp("rtp"); RtpTransportParameters parameters; parameters.rtcp.mux = false; auto result = ortc_factory_->CreateRtpTransport(parameters, &rtp, nullptr, nullptr); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); } // If the |mux| member of the RtcpParameters is true, only an RTP packet // transport is necessary. So, passing in an RTCP transport is most likely // an accident, and thus should be treated as an error. TEST_F(OrtcFactoryTest, CreateRtpTransportWithExtraneousRtcpTransport) { rtc::FakePacketTransport rtp("rtp"); rtc::FakePacketTransport rtcp("rtcp"); auto result = ortc_factory_->CreateRtpTransport(MakeRtcpMuxParameters(), &rtp, &rtcp, nullptr); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); } // Basic test that CreateUdpTransport works with AF_INET and AF_INET6. TEST_F(OrtcFactoryTest, CreateUdpTransport) { auto result = ortc_factory_->CreateUdpTransport(AF_INET); EXPECT_TRUE(result.ok()); result = ortc_factory_->CreateUdpTransport(AF_INET6); EXPECT_TRUE(result.ok()); } // Test CreateUdpPort with the |min_port| and |max_port| arguments. TEST_F(OrtcFactoryTest, CreateUdpTransportWithPortRange) { auto socket_result1 = ortc_factory_->CreateUdpTransport(AF_INET, 2000, 2002); ASSERT_TRUE(socket_result1.ok()); EXPECT_EQ(2000, socket_result1.value()->GetLocalAddress().port()); auto socket_result2 = ortc_factory_->CreateUdpTransport(AF_INET, 2000, 2002); ASSERT_TRUE(socket_result2.ok()); EXPECT_EQ(2001, socket_result2.value()->GetLocalAddress().port()); auto socket_result3 = ortc_factory_->CreateUdpTransport(AF_INET, 2000, 2002); ASSERT_TRUE(socket_result3.ok()); EXPECT_EQ(2002, socket_result3.value()->GetLocalAddress().port()); // All sockets in the range have been exhausted, so the next call should // fail. auto failed_result = ortc_factory_->CreateUdpTransport(AF_INET, 2000, 2002); EXPECT_EQ(RTCErrorType::RESOURCE_EXHAUSTED, failed_result.error().type()); // If one socket is destroyed, that port should be freed up again. socket_result2.MoveValue().reset(); auto socket_result4 = ortc_factory_->CreateUdpTransport(AF_INET, 2000, 2002); ASSERT_TRUE(socket_result4.ok()); EXPECT_EQ(2001, socket_result4.value()->GetLocalAddress().port()); } // Basic test that CreateUdpTransport works with AF_INET and AF_INET6. TEST_F(OrtcFactoryTest, CreateUdpTransportWithInvalidAddressFamily) { auto result = ortc_factory_->CreateUdpTransport(12345); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); } TEST_F(OrtcFactoryTest, CreateUdpTransportWithInvalidPortRange) { auto result = ortc_factory_->CreateUdpTransport(AF_INET, 3000, 2000); EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type()); } // Just sanity check that each "GetCapabilities" method returns some codecs. TEST_F(OrtcFactoryTest, GetSenderAndReceiverCapabilities) { RtpCapabilities audio_send_caps = ortc_factory_->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO); EXPECT_GT(audio_send_caps.codecs.size(), 0u); RtpCapabilities video_send_caps = ortc_factory_->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO); EXPECT_GT(video_send_caps.codecs.size(), 0u); RtpCapabilities audio_receive_caps = ortc_factory_->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_AUDIO); EXPECT_GT(audio_receive_caps.codecs.size(), 0u); RtpCapabilities video_receive_caps = ortc_factory_->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_VIDEO); EXPECT_GT(video_receive_caps.codecs.size(), 0u); } // Calling CreateRtpSender with a null track should fail, since that makes it // impossible to know whether to create an audio or video sender. The // application should be using the method that takes a cricket::MediaType // instead. TEST_F(OrtcFactoryTest, CreateSenderWithNullTrack) { auto rtp_transport = CreateRtpTransportWithFakePacketTransport(); auto result = ortc_factory_->CreateRtpSender(nullptr, rtp_transport.get()); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type()); } // Calling CreateRtpSender or CreateRtpReceiver with MEDIA_TYPE_DATA should // fail. TEST_F(OrtcFactoryTest, CreateSenderOrReceieverWithInvalidKind) { auto rtp_transport = CreateRtpTransportWithFakePacketTransport(); auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_DATA, rtp_transport.get()); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, sender_result.error().type()); auto receiver_result = ortc_factory_->CreateRtpReceiver( cricket::MEDIA_TYPE_DATA, rtp_transport.get()); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, receiver_result.error().type()); } TEST_F(OrtcFactoryTest, CreateSendersOrReceieversWithNullTransport) { auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_AUDIO, nullptr); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, sender_result.error().type()); auto receiver_result = ortc_factory_->CreateRtpReceiver(cricket::MEDIA_TYPE_AUDIO, nullptr); EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, receiver_result.error().type()); } } // namespace webrtc