1 /* 2 * libjingle 3 * Copyright 2008 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/app/webrtc/fakemediacontroller.h" 29 #include "talk/media/base/fakecapturemanager.h" 30 #include "talk/media/base/fakemediaengine.h" 31 #include "talk/media/base/fakevideocapturer.h" 32 #include "talk/media/base/testutils.h" 33 #include "talk/media/webrtc/fakewebrtccall.h" 34 #include "talk/session/media/channelmanager.h" 35 #include "webrtc/base/gunit.h" 36 #include "webrtc/base/logging.h" 37 #include "webrtc/base/thread.h" 38 #include "webrtc/p2p/base/faketransportcontroller.h" 39 40 namespace cricket { 41 42 static const AudioCodec kAudioCodecs[] = { 43 AudioCodec(97, "voice", 1, 2, 3, 0), 44 AudioCodec(111, "OPUS", 48000, 32000, 2, 0), 45 }; 46 47 static const VideoCodec kVideoCodecs[] = { 48 VideoCodec(99, "H264", 100, 200, 300, 0), 49 VideoCodec(100, "VP8", 100, 200, 300, 0), 50 VideoCodec(96, "rtx", 100, 200, 300, 0), 51 }; 52 53 class ChannelManagerTest : public testing::Test { 54 protected: 55 ChannelManagerTest() 56 : fme_(new cricket::FakeMediaEngine()), 57 fdme_(new cricket::FakeDataEngine()), 58 fcm_(new cricket::FakeCaptureManager()), 59 cm_(new cricket::ChannelManager(fme_, 60 fdme_, 61 fcm_, 62 rtc::Thread::Current())), 63 fake_call_(webrtc::Call::Config()), 64 fake_mc_(cm_, &fake_call_), 65 transport_controller_( 66 new cricket::FakeTransportController(ICEROLE_CONTROLLING)) {} 67 68 virtual void SetUp() { 69 fme_->SetAudioCodecs(MAKE_VECTOR(kAudioCodecs)); 70 fme_->SetVideoCodecs(MAKE_VECTOR(kVideoCodecs)); 71 } 72 73 virtual void TearDown() { 74 delete transport_controller_; 75 delete cm_; 76 cm_ = NULL; 77 fcm_ = NULL; 78 fdme_ = NULL; 79 fme_ = NULL; 80 } 81 82 rtc::Thread worker_; 83 cricket::FakeMediaEngine* fme_; 84 cricket::FakeDataEngine* fdme_; 85 cricket::FakeCaptureManager* fcm_; 86 cricket::ChannelManager* cm_; 87 cricket::FakeCall fake_call_; 88 cricket::FakeMediaController fake_mc_; 89 cricket::FakeTransportController* transport_controller_; 90 }; 91 92 // Test that we startup/shutdown properly. 93 TEST_F(ChannelManagerTest, StartupShutdown) { 94 EXPECT_FALSE(cm_->initialized()); 95 EXPECT_EQ(rtc::Thread::Current(), cm_->worker_thread()); 96 EXPECT_TRUE(cm_->Init()); 97 EXPECT_TRUE(cm_->initialized()); 98 cm_->Terminate(); 99 EXPECT_FALSE(cm_->initialized()); 100 } 101 102 // Test that we startup/shutdown properly with a worker thread. 103 TEST_F(ChannelManagerTest, StartupShutdownOnThread) { 104 worker_.Start(); 105 EXPECT_FALSE(cm_->initialized()); 106 EXPECT_EQ(rtc::Thread::Current(), cm_->worker_thread()); 107 EXPECT_TRUE(cm_->set_worker_thread(&worker_)); 108 EXPECT_EQ(&worker_, cm_->worker_thread()); 109 EXPECT_TRUE(cm_->Init()); 110 EXPECT_TRUE(cm_->initialized()); 111 // Setting the worker thread while initialized should fail. 112 EXPECT_FALSE(cm_->set_worker_thread(rtc::Thread::Current())); 113 cm_->Terminate(); 114 EXPECT_FALSE(cm_->initialized()); 115 } 116 117 // Test that we can create and destroy a voice and video channel. 118 TEST_F(ChannelManagerTest, CreateDestroyChannels) { 119 EXPECT_TRUE(cm_->Init()); 120 cricket::VoiceChannel* voice_channel = 121 cm_->CreateVoiceChannel(&fake_mc_, transport_controller_, 122 cricket::CN_AUDIO, false, AudioOptions()); 123 EXPECT_TRUE(voice_channel != nullptr); 124 cricket::VideoChannel* video_channel = 125 cm_->CreateVideoChannel(&fake_mc_, transport_controller_, 126 cricket::CN_VIDEO, false, VideoOptions()); 127 EXPECT_TRUE(video_channel != nullptr); 128 cricket::DataChannel* data_channel = cm_->CreateDataChannel( 129 transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP); 130 EXPECT_TRUE(data_channel != nullptr); 131 cm_->DestroyVideoChannel(video_channel); 132 cm_->DestroyVoiceChannel(voice_channel); 133 cm_->DestroyDataChannel(data_channel); 134 cm_->Terminate(); 135 } 136 137 // Test that we can create and destroy a voice and video channel with a worker. 138 TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) { 139 worker_.Start(); 140 EXPECT_TRUE(cm_->set_worker_thread(&worker_)); 141 EXPECT_TRUE(cm_->Init()); 142 delete transport_controller_; 143 transport_controller_ = 144 new cricket::FakeTransportController(&worker_, ICEROLE_CONTROLLING); 145 cricket::VoiceChannel* voice_channel = 146 cm_->CreateVoiceChannel(&fake_mc_, transport_controller_, 147 cricket::CN_AUDIO, false, AudioOptions()); 148 EXPECT_TRUE(voice_channel != nullptr); 149 cricket::VideoChannel* video_channel = 150 cm_->CreateVideoChannel(&fake_mc_, transport_controller_, 151 cricket::CN_VIDEO, false, VideoOptions()); 152 EXPECT_TRUE(video_channel != nullptr); 153 cricket::DataChannel* data_channel = cm_->CreateDataChannel( 154 transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP); 155 EXPECT_TRUE(data_channel != nullptr); 156 cm_->DestroyVideoChannel(video_channel); 157 cm_->DestroyVoiceChannel(voice_channel); 158 cm_->DestroyDataChannel(data_channel); 159 cm_->Terminate(); 160 } 161 162 // Test that we fail to create a voice/video channel if the session is unable 163 // to create a cricket::TransportChannel 164 TEST_F(ChannelManagerTest, NoTransportChannelTest) { 165 EXPECT_TRUE(cm_->Init()); 166 transport_controller_->set_fail_channel_creation(true); 167 // The test is useless unless the session does not fail creating 168 // cricket::TransportChannel. 169 ASSERT_TRUE(transport_controller_->CreateTransportChannel_w( 170 "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP) == nullptr); 171 172 cricket::VoiceChannel* voice_channel = 173 cm_->CreateVoiceChannel(&fake_mc_, transport_controller_, 174 cricket::CN_AUDIO, false, AudioOptions()); 175 EXPECT_TRUE(voice_channel == nullptr); 176 cricket::VideoChannel* video_channel = 177 cm_->CreateVideoChannel(&fake_mc_, transport_controller_, 178 cricket::CN_VIDEO, false, VideoOptions()); 179 EXPECT_TRUE(video_channel == nullptr); 180 cricket::DataChannel* data_channel = cm_->CreateDataChannel( 181 transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP); 182 EXPECT_TRUE(data_channel == nullptr); 183 cm_->Terminate(); 184 } 185 186 TEST_F(ChannelManagerTest, GetSetOutputVolumeBeforeInit) { 187 int level; 188 // Before init, SetOutputVolume() remembers the volume but does not change the 189 // volume of the engine. GetOutputVolume() should fail. 190 EXPECT_EQ(-1, fme_->output_volume()); 191 EXPECT_FALSE(cm_->GetOutputVolume(&level)); 192 EXPECT_FALSE(cm_->SetOutputVolume(-1)); // Invalid volume. 193 EXPECT_TRUE(cm_->SetOutputVolume(99)); 194 EXPECT_EQ(-1, fme_->output_volume()); 195 196 // Init() will apply the remembered volume. 197 EXPECT_TRUE(cm_->Init()); 198 EXPECT_TRUE(cm_->GetOutputVolume(&level)); 199 EXPECT_EQ(99, level); 200 EXPECT_EQ(level, fme_->output_volume()); 201 202 EXPECT_TRUE(cm_->SetOutputVolume(60)); 203 EXPECT_TRUE(cm_->GetOutputVolume(&level)); 204 EXPECT_EQ(60, level); 205 EXPECT_EQ(level, fme_->output_volume()); 206 } 207 208 TEST_F(ChannelManagerTest, GetSetOutputVolume) { 209 int level; 210 EXPECT_TRUE(cm_->Init()); 211 EXPECT_TRUE(cm_->GetOutputVolume(&level)); 212 EXPECT_EQ(level, fme_->output_volume()); 213 214 EXPECT_FALSE(cm_->SetOutputVolume(-1)); // Invalid volume. 215 EXPECT_TRUE(cm_->SetOutputVolume(60)); 216 EXPECT_EQ(60, fme_->output_volume()); 217 EXPECT_TRUE(cm_->GetOutputVolume(&level)); 218 EXPECT_EQ(60, level); 219 } 220 221 TEST_F(ChannelManagerTest, SetVideoRtxEnabled) { 222 std::vector<VideoCodec> codecs; 223 const VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); 224 225 // By default RTX is disabled. 226 cm_->GetSupportedVideoCodecs(&codecs); 227 EXPECT_FALSE(ContainsMatchingCodec(codecs, rtx_codec)); 228 229 // Enable and check. 230 EXPECT_TRUE(cm_->SetVideoRtxEnabled(true)); 231 cm_->GetSupportedVideoCodecs(&codecs); 232 EXPECT_TRUE(ContainsMatchingCodec(codecs, rtx_codec)); 233 234 // Disable and check. 235 EXPECT_TRUE(cm_->SetVideoRtxEnabled(false)); 236 cm_->GetSupportedVideoCodecs(&codecs); 237 EXPECT_FALSE(ContainsMatchingCodec(codecs, rtx_codec)); 238 239 // Cannot toggle rtx after initialization. 240 EXPECT_TRUE(cm_->Init()); 241 EXPECT_FALSE(cm_->SetVideoRtxEnabled(true)); 242 EXPECT_FALSE(cm_->SetVideoRtxEnabled(false)); 243 244 // Can set again after terminate. 245 cm_->Terminate(); 246 EXPECT_TRUE(cm_->SetVideoRtxEnabled(true)); 247 cm_->GetSupportedVideoCodecs(&codecs); 248 EXPECT_TRUE(ContainsMatchingCodec(codecs, rtx_codec)); 249 } 250 251 } // namespace cricket 252