audio_manager_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright 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 "base/environment.h" 6#include "base/logging.h" 7#include "base/memory/scoped_ptr.h" 8#include "media/audio/audio_manager.h" 9#include "media/audio/audio_manager_base.h" 10#include "testing/gtest/include/gtest/gtest.h" 11 12#if defined(OS_LINUX) 13#include "media/audio/linux/audio_manager_linux.h" 14#endif // defined(OS_LINUX) 15 16#if defined(OS_WIN) 17#include "base/win/scoped_com_initializer.h" 18#include "media/audio/win/audio_manager_win.h" 19#include "media/audio/win/wavein_input_win.h" 20#endif 21 22#if defined(USE_PULSEAUDIO) 23#include "media/audio/pulse/audio_manager_pulse.h" 24#endif // defined(USE_PULSEAUDIO) 25 26namespace media { 27 28// Test fixture which allows us to override the default enumeration API on 29// Windows. 30class AudioManagerTest 31 : public ::testing::Test { 32 protected: 33 AudioManagerTest() 34 : audio_manager_(AudioManager::Create()) 35#if defined(OS_WIN) 36 , com_init_(base::win::ScopedCOMInitializer::kMTA) 37#endif 38 { 39 } 40 41#if defined(OS_WIN) 42 bool SetMMDeviceEnumeration() { 43 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get()); 44 // Windows Wave is used as default if Windows XP was detected => 45 // return false since MMDevice is not supported on XP. 46 if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration) 47 return false; 48 49 amw->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration); 50 return true; 51 } 52 53 void SetWaveEnumeration() { 54 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get()); 55 amw->SetEnumerationType(AudioManagerWin::kWaveEnumeration); 56 } 57 58 std::string GetDeviceIdFromPCMWaveInAudioInputStream( 59 const std::string& device_id) { 60 AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get()); 61 AudioParameters parameters( 62 AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 63 AudioParameters::kAudioCDSampleRate, 16, 64 1024); 65 scoped_ptr<PCMWaveInAudioInputStream> stream( 66 static_cast<PCMWaveInAudioInputStream*>( 67 amw->CreatePCMWaveInAudioInputStream(parameters, device_id))); 68 return stream.get() ? stream->device_id_ : std::string(); 69 } 70#endif 71 72 // Helper method which verifies that the device list starts with a valid 73 // default record followed by non-default device names. 74 static void CheckDeviceNames(const AudioDeviceNames& device_names) { 75 VLOG(2) << "Got " << device_names.size() << " audio devices."; 76 if (!device_names.empty()) { 77 AudioDeviceNames::const_iterator it = device_names.begin(); 78 79 // The first device in the list should always be the default device. 80 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName), 81 it->device_name); 82 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id); 83 ++it; 84 85 // Other devices should have non-empty name and id and should not contain 86 // default name or id. 87 while (it != device_names.end()) { 88 EXPECT_FALSE(it->device_name.empty()); 89 EXPECT_FALSE(it->unique_id.empty()); 90 VLOG(2) << "Device ID(" << it->unique_id 91 << "), label: " << it->device_name; 92 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName), 93 it->device_name); 94 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId), 95 it->unique_id); 96 ++it; 97 } 98 } else { 99 // Log a warning so we can see the status on the build bots. No need to 100 // break the test though since this does successfully test the code and 101 // some failure cases. 102 LOG(WARNING) << "No input devices detected"; 103 } 104 } 105 106 bool CanRunInputTest() { 107 return audio_manager_->HasAudioInputDevices(); 108 } 109 110 bool CanRunOutputTest() { 111 return audio_manager_->HasAudioOutputDevices(); 112 } 113 114 scoped_ptr<AudioManager> audio_manager_; 115 116#if defined(OS_WIN) 117 // The MMDevice API requires COM to be initialized on the current thread. 118 base::win::ScopedCOMInitializer com_init_; 119#endif 120}; 121 122// Test that devices can be enumerated. 123TEST_F(AudioManagerTest, EnumerateInputDevices) { 124 if (!CanRunInputTest()) 125 return; 126 127 AudioDeviceNames device_names; 128 audio_manager_->GetAudioInputDeviceNames(&device_names); 129 CheckDeviceNames(device_names); 130} 131 132// Test that devices can be enumerated. 133TEST_F(AudioManagerTest, EnumerateOutputDevices) { 134 if (!CanRunOutputTest()) 135 return; 136 137 AudioDeviceNames device_names; 138 audio_manager_->GetAudioOutputDeviceNames(&device_names); 139 CheckDeviceNames(device_names); 140} 141 142// Run additional tests for Windows since enumeration can be done using 143// two different APIs. MMDevice is default for Vista and higher and Wave 144// is default for XP and lower. 145#if defined(OS_WIN) 146 147// Override default enumeration API and force usage of Windows MMDevice. 148// This test will only run on Windows Vista and higher. 149TEST_F(AudioManagerTest, EnumerateInputDevicesWinMMDevice) { 150 if (!CanRunInputTest()) 151 return; 152 153 AudioDeviceNames device_names; 154 if (!SetMMDeviceEnumeration()) { 155 // Usage of MMDevice will fail on XP and lower. 156 LOG(WARNING) << "MM device enumeration is not supported."; 157 return; 158 } 159 audio_manager_->GetAudioInputDeviceNames(&device_names); 160 CheckDeviceNames(device_names); 161} 162 163TEST_F(AudioManagerTest, EnumerateOutputDevicesWinMMDevice) { 164 if (!CanRunOutputTest()) 165 return; 166 167 AudioDeviceNames device_names; 168 if (!SetMMDeviceEnumeration()) { 169 // Usage of MMDevice will fail on XP and lower. 170 LOG(WARNING) << "MM device enumeration is not supported."; 171 return; 172 } 173 audio_manager_->GetAudioOutputDeviceNames(&device_names); 174 CheckDeviceNames(device_names); 175} 176 177// Override default enumeration API and force usage of Windows Wave. 178// This test will run on Windows XP, Windows Vista and Windows 7. 179TEST_F(AudioManagerTest, EnumerateInputDevicesWinWave) { 180 if (!CanRunInputTest()) 181 return; 182 183 AudioDeviceNames device_names; 184 SetWaveEnumeration(); 185 audio_manager_->GetAudioInputDeviceNames(&device_names); 186 CheckDeviceNames(device_names); 187} 188 189TEST_F(AudioManagerTest, EnumerateOutputDevicesWinWave) { 190 if (!CanRunOutputTest()) 191 return; 192 193 AudioDeviceNames device_names; 194 SetWaveEnumeration(); 195 audio_manager_->GetAudioOutputDeviceNames(&device_names); 196 CheckDeviceNames(device_names); 197} 198 199TEST_F(AudioManagerTest, WinXPDeviceIdUnchanged) { 200 if (!CanRunInputTest()) 201 return; 202 203 AudioDeviceNames xp_device_names; 204 SetWaveEnumeration(); 205 audio_manager_->GetAudioInputDeviceNames(&xp_device_names); 206 CheckDeviceNames(xp_device_names); 207 208 // Device ID should remain unchanged, including the default device ID. 209 for (AudioDeviceNames::iterator i = xp_device_names.begin(); 210 i != xp_device_names.end(); ++i) { 211 EXPECT_EQ(i->unique_id, 212 GetDeviceIdFromPCMWaveInAudioInputStream(i->unique_id)); 213 } 214} 215 216TEST_F(AudioManagerTest, ConvertToWinXPInputDeviceId) { 217 if (!CanRunInputTest()) 218 return; 219 220 if (!SetMMDeviceEnumeration()) { 221 // Usage of MMDevice will fail on XP and lower. 222 LOG(WARNING) << "MM device enumeration is not supported."; 223 return; 224 } 225 226 AudioDeviceNames device_names; 227 audio_manager_->GetAudioInputDeviceNames(&device_names); 228 CheckDeviceNames(device_names); 229 230 for (AudioDeviceNames::iterator i = device_names.begin(); 231 i != device_names.end(); ++i) { 232 std::string converted_id = 233 GetDeviceIdFromPCMWaveInAudioInputStream(i->unique_id); 234 if (i == device_names.begin()) { 235 // The first in the list is the default device ID, which should not be 236 // changed when passed to PCMWaveInAudioInputStream. 237 EXPECT_EQ(i->unique_id, converted_id); 238 } else { 239 // MMDevice-style device IDs should be converted to WaveIn-style device 240 // IDs. 241 EXPECT_NE(i->unique_id, converted_id); 242 } 243 } 244} 245 246#endif // defined(OS_WIN) 247 248#if defined(USE_PULSEAUDIO) 249// On Linux, there are two implementations available and both can 250// sometimes be tested on a single system. These tests specifically 251// test Pulseaudio. 252 253TEST_F(AudioManagerTest, EnumerateInputDevicesPulseaudio) { 254 if (!CanRunInputTest()) 255 return; 256 257 audio_manager_.reset(AudioManagerPulse::Create()); 258 if (audio_manager_.get()) { 259 AudioDeviceNames device_names; 260 audio_manager_->GetAudioInputDeviceNames(&device_names); 261 CheckDeviceNames(device_names); 262 } else { 263 LOG(WARNING) << "No pulseaudio on this system."; 264 } 265} 266 267TEST_F(AudioManagerTest, EnumerateOutputDevicesPulseaudio) { 268 if (!CanRunOutputTest()) 269 return; 270 271 audio_manager_.reset(AudioManagerPulse::Create()); 272 if (audio_manager_.get()) { 273 AudioDeviceNames device_names; 274 audio_manager_->GetAudioOutputDeviceNames(&device_names); 275 CheckDeviceNames(device_names); 276 } else { 277 LOG(WARNING) << "No pulseaudio on this system."; 278 } 279} 280#endif // defined(USE_PULSEAUDIO) 281 282#if defined(USE_ALSA) 283// On Linux, there are two implementations available and both can 284// sometimes be tested on a single system. These tests specifically 285// test Alsa. 286 287TEST_F(AudioManagerTest, EnumerateInputDevicesAlsa) { 288 if (!CanRunInputTest()) 289 return; 290 291 VLOG(2) << "Testing AudioManagerLinux."; 292 audio_manager_.reset(new AudioManagerLinux()); 293 AudioDeviceNames device_names; 294 audio_manager_->GetAudioInputDeviceNames(&device_names); 295 CheckDeviceNames(device_names); 296} 297 298TEST_F(AudioManagerTest, EnumerateOutputDevicesAlsa) { 299 if (!CanRunOutputTest()) 300 return; 301 302 VLOG(2) << "Testing AudioManagerLinux."; 303 audio_manager_.reset(new AudioManagerLinux()); 304 AudioDeviceNames device_names; 305 audio_manager_->GetAudioOutputDeviceNames(&device_names); 306 CheckDeviceNames(device_names); 307} 308#endif // defined(USE_ALSA) 309 310TEST_F(AudioManagerTest, GetDefaultOutputStreamParameters) { 311#if defined(OS_WIN) || defined(OS_MACOSX) 312 if (!CanRunInputTest()) 313 return; 314 315 AudioParameters params = audio_manager_->GetDefaultOutputStreamParameters(); 316 EXPECT_TRUE(params.IsValid()); 317#endif // defined(OS_WIN) || defined(OS_MACOSX) 318} 319 320TEST_F(AudioManagerTest, GetAssociatedOutputDeviceID) { 321#if defined(OS_WIN) || defined(OS_MACOSX) 322 if (!CanRunInputTest() || !CanRunOutputTest()) 323 return; 324 325 AudioDeviceNames device_names; 326 audio_manager_->GetAudioInputDeviceNames(&device_names); 327 bool found_an_associated_device = false; 328 for (AudioDeviceNames::iterator it = device_names.begin(); 329 it != device_names.end(); 330 ++it) { 331 EXPECT_FALSE(it->unique_id.empty()); 332 EXPECT_FALSE(it->device_name.empty()); 333 std::string output_device_id( 334 audio_manager_->GetAssociatedOutputDeviceID(it->unique_id)); 335 if (!output_device_id.empty()) { 336 VLOG(2) << it->unique_id << " matches with " << output_device_id; 337 found_an_associated_device = true; 338 } 339 } 340 341 EXPECT_TRUE(found_an_associated_device); 342#endif // defined(OS_WIN) || defined(OS_MACOSX) 343} 344 345} // namespace media 346