audio_input_device_manager_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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_METHOD3(Error, void(MediaStreamType, int, MediaStreamProviderError)); 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 // Returns true iff machine has an audio input device. 58 bool CanRunAudioInputDeviceTests() { 59 return audio_manager_->HasAudioInputDevices(); 60 } 61 62 protected: 63 virtual void SetUp() OVERRIDE { 64 // The test must run on Browser::IO. 65 message_loop_.reset(new base::MessageLoopForIO); 66 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, 67 message_loop_.get())); 68 audio_manager_.reset(media::AudioManager::CreateForTesting()); 69 // Wait for audio thread initialization to complete. Otherwise the 70 // enumeration type may not have been set yet. 71 base::WaitableEvent event(false, false); 72 audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind( 73 &base::WaitableEvent::Signal, base::Unretained(&event))); 74 event.Wait(); 75 manager_ = new AudioInputDeviceManager(audio_manager_.get()); 76 audio_input_listener_.reset(new MockAudioInputDeviceManagerListener()); 77 manager_->Register(audio_input_listener_.get(), 78 message_loop_->message_loop_proxy().get()); 79 80 // Gets the enumerated device list from the AudioInputDeviceManager. 81 manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE); 82 EXPECT_CALL(*audio_input_listener_, 83 DevicesEnumerated(MEDIA_DEVICE_AUDIO_CAPTURE, _)) 84 .Times(1) 85 .WillOnce(SaveArg<1>(&devices_)); 86 87 // Wait until we get the list. 88 message_loop_->RunUntilIdle(); 89 } 90 91 virtual void TearDown() OVERRIDE { 92 manager_->Unregister(); 93 io_thread_.reset(); 94 } 95 96 scoped_ptr<base::MessageLoop> message_loop_; 97 scoped_ptr<BrowserThreadImpl> io_thread_; 98 scoped_refptr<AudioInputDeviceManager> manager_; 99 scoped_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_; 100 scoped_ptr<media::AudioManager> audio_manager_; 101 StreamDeviceInfoArray devices_; 102 103 private: 104 DISALLOW_COPY_AND_ASSIGN(MAYBE_AudioInputDeviceManagerTest); 105}; 106 107// Opens and closes the devices. 108TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenAndCloseDevice) { 109 if (!CanRunAudioInputDeviceTests()) 110 return; 111 112 ASSERT_FALSE(devices_.empty()); 113 114 InSequence s; 115 116 for (StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 117 iter != devices_.end(); ++iter) { 118 // Opens/closes the devices. 119 int session_id = manager_->Open(*iter); 120 121 // Expected mock call with expected return value. 122 EXPECT_CALL(*audio_input_listener_, 123 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 124 .Times(1); 125 // Waits for the callback. 126 message_loop_->RunUntilIdle(); 127 128 manager_->Close(session_id); 129 EXPECT_CALL(*audio_input_listener_, 130 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 131 .Times(1); 132 133 // Waits for the callback. 134 message_loop_->RunUntilIdle(); 135 } 136} 137 138// Opens multiple devices at one time and closes them later. 139TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenMultipleDevices) { 140 if (!CanRunAudioInputDeviceTests()) 141 return; 142 143 ASSERT_FALSE(devices_.empty()); 144 145 InSequence s; 146 147 int index = 0; 148 scoped_ptr<int[]> session_id(new int[devices_.size()]); 149 150 // Opens the devices in a loop. 151 for (StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 152 iter != devices_.end(); ++iter, ++index) { 153 // Opens the devices. 154 session_id[index] = manager_->Open(*iter); 155 156 // Expected mock call with expected returned value. 157 EXPECT_CALL(*audio_input_listener_, 158 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index])) 159 .Times(1); 160 161 // Waits for the callback. 162 message_loop_->RunUntilIdle(); 163 } 164 165 // Checks if the session_ids are unique. 166 for (size_t i = 0; i < devices_.size() - 1; ++i) { 167 for (size_t k = i + 1; k < devices_.size(); ++k) { 168 EXPECT_TRUE(session_id[i] != session_id[k]); 169 } 170 } 171 172 for (size_t i = 0; i < devices_.size(); ++i) { 173 // Closes the devices. 174 manager_->Close(session_id[i]); 175 EXPECT_CALL(*audio_input_listener_, 176 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[i])) 177 .Times(1); 178 179 // Waits for the callback. 180 message_loop_->RunUntilIdle(); 181 } 182} 183 184// Opens a non-existing device. 185TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenNotExistingDevice) { 186 if (!CanRunAudioInputDeviceTests()) 187 return; 188 InSequence s; 189 190 MediaStreamType stream_type = MEDIA_DEVICE_AUDIO_CAPTURE; 191 std::string device_name("device_doesnt_exist"); 192 std::string device_id("id_doesnt_exist"); 193 int sample_rate(0); 194 int channel_config(0); 195 StreamDeviceInfo dummy_device( 196 stream_type, device_name, device_id, sample_rate, channel_config, 2048); 197 198 int session_id = manager_->Open(dummy_device); 199 EXPECT_CALL(*audio_input_listener_, 200 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 201 .Times(1); 202 203 // Waits for the callback. 204 message_loop_->RunUntilIdle(); 205} 206 207// Opens default device twice. 208TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenDeviceTwice) { 209 if (!CanRunAudioInputDeviceTests()) 210 return; 211 212 ASSERT_FALSE(devices_.empty()); 213 214 InSequence s; 215 216 // Opens and closes the default device twice. 217 int first_session_id = manager_->Open(devices_.front()); 218 int second_session_id = manager_->Open(devices_.front()); 219 220 // Expected mock calls with expected returned values. 221 EXPECT_NE(first_session_id, second_session_id); 222 EXPECT_CALL(*audio_input_listener_, 223 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, first_session_id)) 224 .Times(1); 225 EXPECT_CALL(*audio_input_listener_, 226 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id)) 227 .Times(1); 228 // Waits for the callback. 229 message_loop_->RunUntilIdle(); 230 231 manager_->Close(first_session_id); 232 manager_->Close(second_session_id); 233 EXPECT_CALL(*audio_input_listener_, 234 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, first_session_id)) 235 .Times(1); 236 EXPECT_CALL(*audio_input_listener_, 237 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, second_session_id)) 238 .Times(1); 239 // Waits for the callback. 240 message_loop_->RunUntilIdle(); 241} 242 243// Accesses then closes the sessions after opening the devices. 244TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessAndCloseSession) { 245 if (!CanRunAudioInputDeviceTests()) 246 return; 247 248 ASSERT_FALSE(devices_.empty()); 249 250 InSequence s; 251 252 int index = 0; 253 scoped_ptr<int[]> session_id(new int[devices_.size()]); 254 255 // Loops through the devices and calls Open()/Close()/GetOpenedDeviceInfoById 256 // for each device. 257 for (StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 258 iter != devices_.end(); ++iter, ++index) { 259 // Note that no DeviceStopped() notification for Event Handler as we have 260 // stopped the device before calling close. 261 session_id[index] = manager_->Open(*iter); 262 EXPECT_CALL(*audio_input_listener_, 263 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index])) 264 .Times(1); 265 message_loop_->RunUntilIdle(); 266 267 const StreamDeviceInfo* info = manager_->GetOpenedDeviceInfoById( 268 session_id[index]); 269 DCHECK(info); 270 EXPECT_EQ(iter->device.id, info->device.id); 271 manager_->Close(session_id[index]); 272 EXPECT_CALL(*audio_input_listener_, 273 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id[index])) 274 .Times(1); 275 message_loop_->RunUntilIdle(); 276 } 277} 278 279// Access an invalid session. 280TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessInvalidSession) { 281 if (!CanRunAudioInputDeviceTests()) 282 return; 283 InSequence s; 284 285 // Opens the first device. 286 StreamDeviceInfoArray::const_iterator iter = devices_.begin(); 287 int session_id = manager_->Open(*iter); 288 EXPECT_CALL(*audio_input_listener_, 289 Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 290 .Times(1); 291 message_loop_->RunUntilIdle(); 292 293 // Access a non-opened device. 294 // This should fail and return an empty StreamDeviceInfo. 295 int invalid_session_id = session_id + 1; 296 const StreamDeviceInfo* info = 297 manager_->GetOpenedDeviceInfoById(invalid_session_id); 298 DCHECK(!info); 299 300 manager_->Close(session_id); 301 EXPECT_CALL(*audio_input_listener_, 302 Closed(MEDIA_DEVICE_AUDIO_CAPTURE, session_id)) 303 .Times(1); 304 message_loop_->RunUntilIdle(); 305} 306 307} // namespace content 308