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.
5 #include "base/environment.h"
6 #include "base/logging.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "media/audio/audio_manager.h"
10 #include "media/audio/audio_manager_base.h"
11 #include "media/audio/fake_audio_log_factory.h"
12 #include "testing/gtest/include/gtest/gtest.h"
15 #include "media/audio/alsa/audio_manager_alsa.h"
16 #endif // defined(USE_ALSA)
19 #include "base/win/scoped_com_initializer.h"
20 #include "media/audio/win/audio_manager_win.h"
21 #include "media/audio/win/wavein_input_win.h"
24 #if defined(USE_PULSEAUDIO)
25 #include "media/audio/pulse/audio_manager_pulse.h"
26 #endif // defined(USE_PULSEAUDIO)
30 // Test fixture which allows us to override the default enumeration API on
32 class AudioManagerTest
33 : public ::testing::Test
{
36 : audio_manager_(AudioManager::CreateForTesting())
38 , com_init_(base::win::ScopedCOMInitializer::kMTA
)
41 // Wait for audio thread initialization to complete. Otherwise the
42 // enumeration type may not have been set yet.
43 base::WaitableEvent
event(false, false);
44 audio_manager_
->GetTaskRunner()->PostTask(FROM_HERE
, base::Bind(
45 &base::WaitableEvent::Signal
, base::Unretained(&event
)));
50 bool SetMMDeviceEnumeration() {
51 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
52 // Windows Wave is used as default if Windows XP was detected =>
53 // return false since MMDevice is not supported on XP.
54 if (amw
->enumeration_type() == AudioManagerWin::kWaveEnumeration
)
57 amw
->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration
);
61 void SetWaveEnumeration() {
62 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
63 amw
->SetEnumerationType(AudioManagerWin::kWaveEnumeration
);
66 std::string
GetDeviceIdFromPCMWaveInAudioInputStream(
67 const std::string
& device_id
) {
68 AudioManagerWin
* amw
= static_cast<AudioManagerWin
*>(audio_manager_
.get());
69 AudioParameters
parameters(
70 AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_STEREO
,
71 AudioParameters::kAudioCDSampleRate
, 16,
73 scoped_ptr
<PCMWaveInAudioInputStream
> stream(
74 static_cast<PCMWaveInAudioInputStream
*>(
75 amw
->CreatePCMWaveInAudioInputStream(parameters
, device_id
)));
76 return stream
.get() ? stream
->device_id_
: std::string();
80 // Helper method which verifies that the device list starts with a valid
81 // default record followed by non-default device names.
82 static void CheckDeviceNames(const AudioDeviceNames
& device_names
) {
83 VLOG(2) << "Got " << device_names
.size() << " audio devices.";
84 if (!device_names
.empty()) {
85 AudioDeviceNames::const_iterator it
= device_names
.begin();
87 // The first device in the list should always be the default device.
88 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName
),
90 EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId
), it
->unique_id
);
93 // Other devices should have non-empty name and id and should not contain
94 // default name or id.
95 while (it
!= device_names
.end()) {
96 EXPECT_FALSE(it
->device_name
.empty());
97 EXPECT_FALSE(it
->unique_id
.empty());
98 VLOG(2) << "Device ID(" << it
->unique_id
99 << "), label: " << it
->device_name
;
100 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName
),
102 EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId
),
107 // Log a warning so we can see the status on the build bots. No need to
108 // break the test though since this does successfully test the code and
109 // some failure cases.
110 LOG(WARNING
) << "No input devices detected";
114 bool CanRunInputTest() {
115 return audio_manager_
->HasAudioInputDevices();
118 bool CanRunOutputTest() {
119 return audio_manager_
->HasAudioOutputDevices();
122 #if defined(USE_ALSA) || defined(USE_PULSEAUDIO)
124 void CreateAudioManagerForTesting() {
125 // Only one AudioManager may exist at a time, so destroy the one we're
126 // currently holding before creating a new one.
127 audio_manager_
.reset();
128 audio_manager_
.reset(T::Create(&fake_audio_log_factory_
));
132 FakeAudioLogFactory fake_audio_log_factory_
;
133 scoped_ptr
<AudioManager
> audio_manager_
;
136 // The MMDevice API requires COM to be initialized on the current thread.
137 base::win::ScopedCOMInitializer com_init_
;
141 // Test that devices can be enumerated.
142 TEST_F(AudioManagerTest
, EnumerateInputDevices
) {
143 if (!CanRunInputTest())
146 AudioDeviceNames device_names
;
147 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
148 CheckDeviceNames(device_names
);
151 // Test that devices can be enumerated.
152 TEST_F(AudioManagerTest
, EnumerateOutputDevices
) {
153 if (!CanRunOutputTest())
156 AudioDeviceNames device_names
;
157 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
158 CheckDeviceNames(device_names
);
161 // Run additional tests for Windows since enumeration can be done using
162 // two different APIs. MMDevice is default for Vista and higher and Wave
163 // is default for XP and lower.
166 // Override default enumeration API and force usage of Windows MMDevice.
167 // This test will only run on Windows Vista and higher.
168 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinMMDevice
) {
169 if (!CanRunInputTest())
172 AudioDeviceNames device_names
;
173 if (!SetMMDeviceEnumeration()) {
174 // Usage of MMDevice will fail on XP and lower.
175 LOG(WARNING
) << "MM device enumeration is not supported.";
178 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
179 CheckDeviceNames(device_names
);
182 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinMMDevice
) {
183 if (!CanRunOutputTest())
186 AudioDeviceNames device_names
;
187 if (!SetMMDeviceEnumeration()) {
188 // Usage of MMDevice will fail on XP and lower.
189 LOG(WARNING
) << "MM device enumeration is not supported.";
192 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
193 CheckDeviceNames(device_names
);
196 // Override default enumeration API and force usage of Windows Wave.
197 // This test will run on Windows XP, Windows Vista and Windows 7.
198 TEST_F(AudioManagerTest
, EnumerateInputDevicesWinWave
) {
199 if (!CanRunInputTest())
202 AudioDeviceNames device_names
;
203 SetWaveEnumeration();
204 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
205 CheckDeviceNames(device_names
);
208 TEST_F(AudioManagerTest
, EnumerateOutputDevicesWinWave
) {
209 if (!CanRunOutputTest())
212 AudioDeviceNames device_names
;
213 SetWaveEnumeration();
214 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
215 CheckDeviceNames(device_names
);
218 TEST_F(AudioManagerTest
, WinXPDeviceIdUnchanged
) {
219 if (!CanRunInputTest())
222 AudioDeviceNames xp_device_names
;
223 SetWaveEnumeration();
224 audio_manager_
->GetAudioInputDeviceNames(&xp_device_names
);
225 CheckDeviceNames(xp_device_names
);
227 // Device ID should remain unchanged, including the default device ID.
228 for (AudioDeviceNames::iterator i
= xp_device_names
.begin();
229 i
!= xp_device_names
.end(); ++i
) {
230 EXPECT_EQ(i
->unique_id
,
231 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
));
235 TEST_F(AudioManagerTest
, ConvertToWinXPInputDeviceId
) {
236 if (!CanRunInputTest())
239 if (!SetMMDeviceEnumeration()) {
240 // Usage of MMDevice will fail on XP and lower.
241 LOG(WARNING
) << "MM device enumeration is not supported.";
245 AudioDeviceNames device_names
;
246 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
247 CheckDeviceNames(device_names
);
249 for (AudioDeviceNames::iterator i
= device_names
.begin();
250 i
!= device_names
.end(); ++i
) {
251 std::string converted_id
=
252 GetDeviceIdFromPCMWaveInAudioInputStream(i
->unique_id
);
253 if (i
== device_names
.begin()) {
254 // The first in the list is the default device ID, which should not be
255 // changed when passed to PCMWaveInAudioInputStream.
256 EXPECT_EQ(i
->unique_id
, converted_id
);
258 // MMDevice-style device IDs should be converted to WaveIn-style device
260 EXPECT_NE(i
->unique_id
, converted_id
);
265 #endif // defined(OS_WIN)
267 #if defined(USE_PULSEAUDIO)
268 // On Linux, there are two implementations available and both can
269 // sometimes be tested on a single system. These tests specifically
272 TEST_F(AudioManagerTest
, EnumerateInputDevicesPulseaudio
) {
273 if (!CanRunInputTest())
276 CreateAudioManagerForTesting
<AudioManagerPulse
>();
277 if (audio_manager_
.get()) {
278 AudioDeviceNames device_names
;
279 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
280 CheckDeviceNames(device_names
);
282 LOG(WARNING
) << "No pulseaudio on this system.";
286 TEST_F(AudioManagerTest
, EnumerateOutputDevicesPulseaudio
) {
287 if (!CanRunOutputTest())
290 CreateAudioManagerForTesting
<AudioManagerPulse
>();
291 if (audio_manager_
.get()) {
292 AudioDeviceNames device_names
;
293 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
294 CheckDeviceNames(device_names
);
296 LOG(WARNING
) << "No pulseaudio on this system.";
299 #endif // defined(USE_PULSEAUDIO)
301 #if defined(USE_ALSA)
302 // On Linux, there are two implementations available and both can
303 // sometimes be tested on a single system. These tests specifically
306 TEST_F(AudioManagerTest
, EnumerateInputDevicesAlsa
) {
307 if (!CanRunInputTest())
310 VLOG(2) << "Testing AudioManagerAlsa.";
311 CreateAudioManagerForTesting
<AudioManagerAlsa
>();
312 AudioDeviceNames device_names
;
313 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
314 CheckDeviceNames(device_names
);
317 TEST_F(AudioManagerTest
, EnumerateOutputDevicesAlsa
) {
318 if (!CanRunOutputTest())
321 VLOG(2) << "Testing AudioManagerAlsa.";
322 CreateAudioManagerForTesting
<AudioManagerAlsa
>();
323 AudioDeviceNames device_names
;
324 audio_manager_
->GetAudioOutputDeviceNames(&device_names
);
325 CheckDeviceNames(device_names
);
327 #endif // defined(USE_ALSA)
329 TEST_F(AudioManagerTest
, GetDefaultOutputStreamParameters
) {
330 #if defined(OS_WIN) || defined(OS_MACOSX)
331 if (!CanRunInputTest())
334 AudioParameters params
= audio_manager_
->GetDefaultOutputStreamParameters();
335 EXPECT_TRUE(params
.IsValid());
336 #endif // defined(OS_WIN) || defined(OS_MACOSX)
339 TEST_F(AudioManagerTest
, GetAssociatedOutputDeviceID
) {
340 #if defined(OS_WIN) || defined(OS_MACOSX)
341 if (!CanRunInputTest() || !CanRunOutputTest())
344 AudioDeviceNames device_names
;
345 audio_manager_
->GetAudioInputDeviceNames(&device_names
);
346 bool found_an_associated_device
= false;
347 for (AudioDeviceNames::iterator it
= device_names
.begin();
348 it
!= device_names
.end();
350 EXPECT_FALSE(it
->unique_id
.empty());
351 EXPECT_FALSE(it
->device_name
.empty());
352 std::string
output_device_id(
353 audio_manager_
->GetAssociatedOutputDeviceID(it
->unique_id
));
354 if (!output_device_id
.empty()) {
355 VLOG(2) << it
->unique_id
<< " matches with " << output_device_id
;
356 found_an_associated_device
= true;
360 EXPECT_TRUE(found_an_associated_device
);
361 #endif // defined(OS_WIN) || defined(OS_MACOSX)