1// Copyright (c) 2012 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 <string> 6 7#include "base/bind.h" 8#include "base/memory/ref_counted.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/message_loop/message_loop.h" 11#include "base/synchronization/waitable_event.h" 12#include "content/browser/browser_thread_impl.h" 13#include "content/browser/renderer_host/media/audio_input_device_manager.h" 14#include "content/public/common/media_stream_request.h" 15#include "media/audio/audio_manager_base.h" 16#include "testing/gmock/include/gmock/gmock.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19using testing::_; 20using testing::InSequence; 21using testing::SaveArg; 22using testing::Return; 23 24namespace content { 25 26class MockAudioInputDeviceManagerListener 27 : public MediaStreamProviderListener { 28 public: 29 MockAudioInputDeviceManagerListener() {} 30 virtual ~MockAudioInputDeviceManagerListener() {} 31 32 MOCK_METHOD2(Opened, void(MediaStreamType, const int)); 33 MOCK_METHOD2(Closed, void(MediaStreamType, const int)); 34 MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType, 35 const StreamDeviceInfoArray&)); 36 MOCK_METHOD2(Aborted, void(MediaStreamType, int)); 37 38 StreamDeviceInfoArray devices_; 39 40 private: 41 DISALLOW_COPY_AND_ASSIGN(MockAudioInputDeviceManagerListener); 42}; 43 44// TODO(henrika): there are special restrictions for Android since 45// AudioInputDeviceManager::Open() must be called on the audio thread. 46// This test suite must be modified to run on Android. 47#if defined(OS_ANDROID) 48#define MAYBE_AudioInputDeviceManagerTest DISABLED_AudioInputDeviceManagerTest 49#else 50#define MAYBE_AudioInputDeviceManagerTest AudioInputDeviceManagerTest 51#endif 52 53class MAYBE_AudioInputDeviceManagerTest : public testing::Test { 54 public: 55 MAYBE_AudioInputDeviceManagerTest() {} 56 57 protected: 58 virtual void SetUp() OVERRIDE { 59 // The test must run on Browser::IO. 60 message_loop_.reset(new base::MessageLoopForIO); 61 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, 62 message_loop_.get())); 63 audio_manager_.reset(media::AudioManager::CreateForTesting()); 64 // Wait for audio thread initialization to complete. Otherwise the 65 // enumeration type may not have been set yet. 66 base::WaitableEvent event(false, false); 67 audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind( 68 &base::WaitableEvent::Signal, base::Unretained(&event))); 69 event.Wait(); 70 manager_ = new AudioInputDeviceManager(audio_manager_.get()); 71 manager_->UseFakeDevice(); 72 audio_input_listener_.reset(new MockAudioInputDeviceManagerListener()); 73 manager_->Register(audio_input_listener_.get(), 74 message_loop_->message_loop_proxy().get()); 75 76 // Gets the enumerated device list from the AudioInputDeviceManager. 77 manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE); 78 EXPECT_CALL(*audio_input_listener_, 79 DevicesEnumerated(MEDIA_DEVICE_AUDIO_CAPTURE, _)) 80 .Times(1) 81 .WillOnce(SaveArg<1>(&devices_)); 82 83 // Wait until we get the list. 84 message_loop_->RunUntilIdle(); 85 } 86 87 virtual void TearDown() OVERRIDE { 88 manager_->Unregister(); 89 io_thread_.reset(); 90 } 91 92 scoped_ptr<base::MessageLoop> message_loop_; 93 scoped_ptr<BrowserThreadImpl> io_thread_; 94 scoped_refptr<AudioInputDeviceManager> manager_; 95 scoped_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_; 96 scoped_ptr<media::AudioManager> audio_manager_; 97 StreamDeviceInfoArray devices_; 98 99 private: 100 DISALLOW_COPY_AND_ASSIGN(MAYBE_AudioInputDeviceManagerTest); 101}; 102 103// Opens and closes the devices. 104TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenAndCloseDevice) { 105 106 ASSERT_FALSE(devices_.empty()); 107 108 InSequence s; 109 110 for (StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 111 iter != devices_.end(); ++iter) { 112 // Opens/closes the devices. 113 int session_id = manager_->Open(*iter); 114 115 // Expected mock call with expected return value. 116 EXPECT_CALL(*audio_input_listener_, 117 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 118 .Times(1); 119 // Waits for the callback. 120 message_loop_->RunUntilIdle(); 121 122 manager_->Close(session_id); 123 EXPECT_CALL(*audio_input_listener_, 124 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 125 .Times(1); 126 127 // Waits for the callback. 128 message_loop_->RunUntilIdle(); 129 } 130} 131 132// Opens multiple devices at one time and closes them later. 133TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenMultipleDevices) { 134 ASSERT_FALSE(devices_.empty()); 135 136 InSequence s; 137 138 int index = 0; 139 scoped_ptr<int[]> session_id(new int[devices_.size()]); 140 141 // Opens the devices in a loop. 142 for (StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 143 iter != devices_.end(); ++iter, ++index) { 144 // Opens the devices. 145 session_id[index] = manager_->Open(*iter); 146 147 // Expected mock call with expected returned value. 148 EXPECT_CALL(*audio_input_listener_, 149 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index])) 150 .Times(1); 151 152 // Waits for the callback. 153 message_loop_->RunUntilIdle(); 154 } 155 156 // Checks if the session_ids are unique. 157 for (size_t i = 0; i < devices_.size() - 1; ++i) { 158 for (size_t k = i + 1; k < devices_.size(); ++k) { 159 EXPECT_TRUE(session_id[i] != session_id[k]); 160 } 161 } 162 163 for (size_t i = 0; i < devices_.size(); ++i) { 164 // Closes the devices. 165 manager_->Close(session_id[i]); 166 EXPECT_CALL(*audio_input_listener_, 167 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[i])) 168 .Times(1); 169 170 // Waits for the callback. 171 message_loop_->RunUntilIdle(); 172 } 173} 174 175// Opens a non-existing device. 176TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenNotExistingDevice) { 177 InSequence s; 178 179 MediaStreamType stream_type = MEDIA_DEVICE_AUDIO_CAPTURE; 180 std::string device_name("device_doesnt_exist"); 181 std::string device_id("id_doesnt_exist"); 182 int sample_rate(0); 183 int channel_config(0); 184 StreamDeviceInfo dummy_device( 185 stream_type, device_name, device_id, sample_rate, channel_config, 2048); 186 187 int session_id = manager_->Open(dummy_device); 188 EXPECT_CALL(*audio_input_listener_, 189 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 190 .Times(1); 191 192 // Waits for the callback. 193 message_loop_->RunUntilIdle(); 194} 195 196// Opens default device twice. 197TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenDeviceTwice) { 198 ASSERT_FALSE(devices_.empty()); 199 200 InSequence s; 201 202 // Opens and closes the default device twice. 203 int first_session_id = manager_->Open(devices_.front()); 204 int second_session_id = manager_->Open(devices_.front()); 205 206 // Expected mock calls with expected returned values. 207 EXPECT_NE(first_session_id, second_session_id); 208 EXPECT_CALL(*audio_input_listener_, 209 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, first_session_id)) 210 .Times(1); 211 EXPECT_CALL(*audio_input_listener_, 212 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id)) 213 .Times(1); 214 // Waits for the callback. 215 message_loop_->RunUntilIdle(); 216 217 manager_->Close(first_session_id); 218 manager_->Close(second_session_id); 219 EXPECT_CALL(*audio_input_listener_, 220 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, first_session_id)) 221 .Times(1); 222 EXPECT_CALL(*audio_input_listener_, 223 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id)) 224 .Times(1); 225 // Waits for the callback. 226 message_loop_->RunUntilIdle(); 227} 228 229// Accesses then closes the sessions after opening the devices. 230TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessAndCloseSession) { 231 ASSERT_FALSE(devices_.empty()); 232 233 InSequence s; 234 235 int index = 0; 236 scoped_ptr<int[]> session_id(new int[devices_.size()]); 237 238 // Loops through the devices and calls Open()/Close()/GetOpenedDeviceInfoById 239 // for each device. 240 for (StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 241 iter != devices_.end(); ++iter, ++index) { 242 // Note that no DeviceStopped() notification for Event Handler as we have 243 // stopped the device before calling close. 244 session_id[index] = manager_->Open(*iter); 245 EXPECT_CALL(*audio_input_listener_, 246 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index])) 247 .Times(1); 248 message_loop_->RunUntilIdle(); 249 250 const StreamDeviceInfo* info = manager_->GetOpenedDeviceInfoById( 251 session_id[index]); 252 DCHECK(info); 253 EXPECT_EQ(iter->device.id, info->device.id); 254 manager_->Close(session_id[index]); 255 EXPECT_CALL(*audio_input_listener_, 256 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index])) 257 .Times(1); 258 message_loop_->RunUntilIdle(); 259 } 260} 261 262// Access an invalid session. 263TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessInvalidSession) { 264 InSequence s; 265 266 // Opens the first device. 267 StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 268 int session_id = manager_->Open(*iter); 269 EXPECT_CALL(*audio_input_listener_, 270 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 271 .Times(1); 272 message_loop_->RunUntilIdle(); 273 274 // Access a non-opened device. 275 // This should fail and return an empty StreamDeviceInfo. 276 int invalid_session_id = session_id + 1; 277 const StreamDeviceInfo* info = 278 manager_->GetOpenedDeviceInfoById(invalid_session_id); 279 DCHECK(!info); 280 281 manager_->Close(session_id); 282 EXPECT_CALL(*audio_input_listener_, 283 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 284 .Times(1); 285 message_loop_->RunUntilIdle(); 286} 287 288} // namespace content 289