1 // Copyright (c) 2013 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 "content/browser/renderer_host/media/audio_mirroring_manager.h" 6 7 #include <map> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/synchronization/waitable_event.h" 13 #include "content/browser/browser_thread_impl.h" 14 #include "media/audio/audio_parameters.h" 15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 using media::AudioOutputStream; 19 using media::AudioParameters; 20 using testing::_; 21 using testing::NotNull; 22 using testing::Ref; 23 using testing::Return; 24 using testing::ReturnRef; 25 26 namespace content { 27 28 namespace { 29 30 class MockDiverter : public AudioMirroringManager::Diverter { 31 public: 32 MOCK_METHOD0(GetAudioParameters, const AudioParameters&()); 33 MOCK_METHOD1(StartDiverting, void(AudioOutputStream*)); 34 MOCK_METHOD0(StopDiverting, void()); 35 }; 36 37 class MockMirroringDestination 38 : public AudioMirroringManager::MirroringDestination { 39 public: 40 MOCK_METHOD1(AddInput, 41 media::AudioOutputStream*(const media::AudioParameters& params)); 42 }; 43 44 } // namespace 45 46 class AudioMirroringManagerTest : public testing::Test { 47 public: 48 AudioMirroringManagerTest() 49 : message_loop_(base::MessageLoop::TYPE_IO), 50 io_thread_(BrowserThread::IO, &message_loop_), 51 params_(AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 52 AudioParameters::kAudioCDSampleRate, 16, 53 AudioParameters::kAudioCDSampleRate / 10) {} 54 55 MockDiverter* CreateStream( 56 int render_process_id, int render_view_id, int expected_times_diverted) { 57 MockDiverter* const diverter = new MockDiverter(); 58 if (expected_times_diverted > 0) { 59 EXPECT_CALL(*diverter, GetAudioParameters()) 60 .Times(expected_times_diverted) 61 .WillRepeatedly(ReturnRef(params_)); 62 EXPECT_CALL(*diverter, StartDiverting(NotNull())) 63 .Times(expected_times_diverted); 64 EXPECT_CALL(*diverter, StopDiverting()) 65 .Times(expected_times_diverted); 66 } 67 68 mirroring_manager_.AddDiverter(render_process_id, render_view_id, diverter); 69 70 return diverter; 71 } 72 73 void KillStream( 74 int render_process_id, int render_view_id, MockDiverter* diverter) { 75 mirroring_manager_.RemoveDiverter( 76 render_process_id, render_view_id, diverter); 77 78 delete diverter; 79 } 80 81 MockMirroringDestination* StartMirroringTo( 82 int render_process_id, int render_view_id, int expected_inputs_added) { 83 MockMirroringDestination* const dest = new MockMirroringDestination(); 84 if (expected_inputs_added > 0) { 85 static AudioOutputStream* const kNonNullPointer = 86 reinterpret_cast<AudioOutputStream*>(0x11111110); 87 EXPECT_CALL(*dest, AddInput(Ref(params_))) 88 .Times(expected_inputs_added) 89 .WillRepeatedly(Return(kNonNullPointer)); 90 } 91 92 mirroring_manager_.StartMirroring(render_process_id, render_view_id, dest); 93 94 return dest; 95 } 96 97 void StopMirroringTo(int render_process_id, int render_view_id, 98 MockMirroringDestination* dest) { 99 mirroring_manager_.StopMirroring(render_process_id, render_view_id, dest); 100 101 delete dest; 102 } 103 104 private: 105 base::MessageLoop message_loop_; 106 BrowserThreadImpl io_thread_; 107 AudioParameters params_; 108 AudioMirroringManager mirroring_manager_; 109 110 DISALLOW_COPY_AND_ASSIGN(AudioMirroringManagerTest); 111 }; 112 113 namespace { 114 const int kRenderProcessId = 123; 115 const int kRenderViewId = 456; 116 const int kAnotherRenderProcessId = 789; 117 const int kAnotherRenderViewId = 1234; 118 const int kYetAnotherRenderProcessId = 4560; 119 const int kYetAnotherRenderViewId = 7890; 120 } 121 122 TEST_F(AudioMirroringManagerTest, MirroringSessionOfNothing) { 123 MockMirroringDestination* const destination = 124 StartMirroringTo(kRenderProcessId, kRenderViewId, 0); 125 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 126 } 127 128 TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) { 129 MockMirroringDestination* const destination = 130 StartMirroringTo(kRenderProcessId, kRenderViewId, 0); 131 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 132 133 MockMirroringDestination* const another_destination = 134 StartMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 0); 135 StopMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 136 another_destination); 137 } 138 139 TEST_F(AudioMirroringManagerTest, SwitchMirroringDestinationNoStreams) { 140 MockMirroringDestination* const destination = 141 StartMirroringTo(kRenderProcessId, kRenderViewId, 0); 142 MockMirroringDestination* const new_destination = 143 StartMirroringTo(kRenderProcessId, kRenderViewId, 0); 144 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 145 StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination); 146 } 147 148 TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundMirroringSession) { 149 MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 1); 150 MockMirroringDestination* const destination = 151 StartMirroringTo(kRenderProcessId, kRenderViewId, 1); 152 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 153 KillStream(kRenderProcessId, kRenderViewId, stream); 154 } 155 156 TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinMirroringSession) { 157 MockMirroringDestination* const destination = 158 StartMirroringTo(kRenderProcessId, kRenderViewId, 1); 159 MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 1); 160 KillStream(kRenderProcessId, kRenderViewId, stream); 161 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 162 } 163 164 TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundTwoMirroringSessions) { 165 MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 2); 166 MockMirroringDestination* const destination = 167 StartMirroringTo(kRenderProcessId, kRenderViewId, 1); 168 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 169 MockMirroringDestination* const new_destination = 170 StartMirroringTo(kRenderProcessId, kRenderViewId, 1); 171 StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination); 172 KillStream(kRenderProcessId, kRenderViewId, stream); 173 } 174 175 TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinTwoMirroringSessions) { 176 MockMirroringDestination* const destination = 177 StartMirroringTo(kRenderProcessId, kRenderViewId, 1); 178 MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 2); 179 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 180 MockMirroringDestination* const new_destination = 181 StartMirroringTo(kRenderProcessId, kRenderViewId, 1); 182 KillStream(kRenderProcessId, kRenderViewId, stream); 183 StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination); 184 } 185 186 TEST_F(AudioMirroringManagerTest, MultipleStreamsInOneMirroringSession) { 187 MockDiverter* const stream1 = 188 CreateStream(kRenderProcessId, kRenderViewId, 1); 189 MockMirroringDestination* const destination = 190 StartMirroringTo(kRenderProcessId, kRenderViewId, 3); 191 MockDiverter* const stream2 = 192 CreateStream(kRenderProcessId, kRenderViewId, 1); 193 MockDiverter* const stream3 = 194 CreateStream(kRenderProcessId, kRenderViewId, 1); 195 KillStream(kRenderProcessId, kRenderViewId, stream2); 196 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 197 KillStream(kRenderProcessId, kRenderViewId, stream3); 198 KillStream(kRenderProcessId, kRenderViewId, stream1); 199 } 200 201 // A random interleaving of operations for three separate targets, each of which 202 // has one stream mirrored to one destination. 203 TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) { 204 MockDiverter* const stream = 205 CreateStream(kRenderProcessId, kRenderViewId, 1); 206 MockMirroringDestination* const destination = 207 StartMirroringTo(kRenderProcessId, kRenderViewId, 1); 208 209 MockMirroringDestination* const another_destination = 210 StartMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 1); 211 MockDiverter* const another_stream = 212 CreateStream(kAnotherRenderProcessId, kAnotherRenderViewId, 1); 213 214 KillStream(kRenderProcessId, kRenderViewId, stream); 215 216 MockDiverter* const yet_another_stream = 217 CreateStream(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 1); 218 MockMirroringDestination* const yet_another_destination = 219 StartMirroringTo(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 1); 220 221 StopMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 222 another_destination); 223 224 StopMirroringTo(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 225 yet_another_destination); 226 227 StopMirroringTo(kRenderProcessId, kRenderViewId, destination); 228 229 KillStream(kAnotherRenderProcessId, kAnotherRenderViewId, another_stream); 230 KillStream(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 231 yet_another_stream); 232 } 233 234 } // namespace content 235